skip to content

Over-Smoothing and Depth

Stack enough rounds and every node representation collapses toward the same vector, which is why two or three layers is the usual depth. Interviewers ask why graph models stay shallow.

on this pageshow

questions

3

What is over-smoothing in a deep graph neural network, and how would you detect it?

level: middleimportance: must knowfreq 62%

answer

  1. repeated averaging is a filter
  2. low-pass, not high-pass
  3. embeddings converge, forward pass
  4. cosine similarity climbing to 1.0
  5. two layers usually still wins

basics

~20 s

Over-smoothing is node embeddings collapsing toward one another as message-passing layers stack, because repeated neighbourhood averaging acts as a low-pass filter. Detect it by logging mean pairwise cosine similarity between node embeddings, which climbs toward 1.0 with depth.

solid answer

~50 s

Each message-passing round replaces a node's vector with a mix of its neighbours' vectors, which is a low-pass filter on the graph. Stack enough rounds and every node in a connected component converges to nearly the same representation — in the linearized case, to a direction fixed by degree — so the classifier on top can no longer separate nodes. I detect it by training the same architecture at 2, 4, 8 and 12 layers and logging **mean pairwise cosine similarity** between node embeddings alongside validation accuracy: the signature is similarity climbing monotonically toward 1.0 while the 2-layer model stays the most accurate. Dirichlet energy — variation along edges — decaying toward zero shows the same thing. Crucially this is a forward-pass collapse, not a gradient problem: the model can train happily and still be useless.

code

python · 21 lines
python
import math

adj = {0: [0, 1], 1: [0, 1, 2], 2: [1, 2, 3], 3: [2, 3]}   # path graph + self-loops
deg = {v: len(n) for v, n in adj.items()}
h = {0: [1.0, 0.0], 1: [0.0, 1.0], 2: [1.0, 1.0], 3: [0.0, -1.0]}

def cos(a, b):
    dot = sum(x * y for x, y in zip(a, b))
    return dot / (math.hypot(*a) * math.hypot(*b))

def mean_pairwise_cos(h):
    pairs = [(u, v) for u in h for v in h if u < v]
    return sum(cos(h[u], h[v]) for u, v in pairs) / len(pairs)

for layer in range(1, 9):
    h = {v: [sum(h[u][d] / math.sqrt(deg[v] * deg[u]) for u in adj[v]) for d in range(2)]
         for v in adj}
    if layer in (1, 2, 4, 8):
        print(layer, round(mean_pairwise_cos(h), 4))

# 1 0.8048 / 2 0.9374 / 4 0.9875 / 8 0.9991

go deeper

for a junior

Be ready to say that graph networks are usually two or three message-passing layers deep and that stacking more typically hurts, and to name the reason as embeddings becoming too similar.

for a middle

You should be able to explain the mechanism: averaging over neighbours is a low-pass filter, repeated application drives representations toward a degree-determined direction, and the fix starts with measuring embedding similarity per depth.

for a senior

Show the diagnostic routine — sweep depth, log similarity and accuracy together, check gradient norms and the training curve to rule out vanishing gradients and overfitting before you touch the architecture.

for a principal

Own the framing that in a plain stack depth buys reach, not capacity, and that reach past the useful radius is actively harmful. Set the team norm of logging an embedding-collapse metric rather than debating layer counts.

### The phenomenon A message-passing graph network updates every node by combining that node's own vector with an aggregate of its neighbours' vectors, then applies a learned transform and a nonlinearity. Stack `k` such layers and every node has mixed information from a widening neighbourhood. **Over-smoothing** is what happens when that mixing goes too far: the node representations stop differing from one another. After enough layers, two nodes in the same connected component carry nearly the same vector, and no classifier sitting on top can tell them apart. The cause is that neighbourhood averaging is a **low-pass filter on the graph**. Each round damps the components of the signal that vary sharply between adjacent nodes and preserves the component that is nearly constant across the graph. Repeat it and only the smooth component survives. ### The linear picture Take the common degree-normalized propagation: with self-loops added, node `v` receives `sum over u in N(v) of h_u / sqrt(d_v * d_u)`, where `d` is the degree including the self-loop. Strip out the nonlinearity and the learned weights for a moment and you are just applying the same normalized-adjacency operator over and over. That operator's largest eigenvalue is 1, and repeated application drives any starting signal toward the corresponding eigenvector — whose entries within a connected component are proportional to `sqrt(d_v)`. So in the limit, embeddings differ only by a degree-dependent scale factor and point in the same direction. Two nodes with the same degree become exactly indistinguishable; every node's angle in embedding space becomes the same. Nonlinearities and learned weights slow this down and complicate it, but they do not change the direction of travel. ### Detecting it You do not need to guess. Instrument the forward pass at each depth and measure how different the node embeddings still are: - **Mean pairwise cosine similarity** between node embeddings. On a healthy 2-layer model this sits well below 1. Train the same architecture at 2, 4, 8 and 12 layers and log the number for each: the over-smoothing signature is that mean similarity climbing monotonically toward 1.0 while validation accuracy peaks at 2 layers and falls from there. - **Dirichlet energy** — the sum over edges of the squared difference between the two endpoint embeddings (usually degree-normalized). It measures how much the signal varies along edges, and it decays toward zero as the stack deepens. - **A layer-wise probe**: freeze the trained model, take the hidden states from each layer, and fit a cheap linear classifier on each. If accuracy rises to layer 2 and then falls, the deeper layers are destroying information rather than adding it. ### What it is not Over-smoothing is **not** vanishing gradients. A deep graph network can train perfectly well — the training loss goes down, gradients are healthy — and still be useless, because the collapse happens in the *forward* pass. Repeated averaging destroys the information before the classifier ever sees it. The tell is the pair of measurements: healthy gradient norms plus rising embedding similarity. It is also not simply overfitting. Overfitting shows as a widening train/validation gap; over-smoothing usually depresses **training** accuracy too, because the representations feeding the head genuinely cannot separate the classes. And it is not a claim that depth is useless in general. It is specific to repeatedly averaging over a fixed graph. Deep stacks that mix in the original features at each layer, or that keep every layer's output available to the readout, remain usable much deeper. ### Why the shallow baseline usually wins This is the practical consequence interviewers want you to state: on standard node-classification benchmarks the strongest plain message-passing model is typically two layers, sometimes three. Two rounds already give each node a two-hop view, which for homophilous graphs — where neighbours tend to share the label — carries most of the usable signal. A third and fourth round add a lot of mixing and very little new evidence, so the smoothing cost overtakes the reach benefit almost immediately. If someone proposes "let's go deeper for more capacity", the right response is that in a plain stack, depth buys *reach*, not capacity, and reach past the useful radius is actively harmful. ### First moves when you see it Widen rather than deepen; keep the shallow model and add width or better features. If depth is genuinely required, use an architecture that resists the collapse — keep the layer-0 representation alive at every layer with an initial-residual term, or let the readout see all layers rather than only the last. Some graph-specific normalizations exist that explicitly re-separate embeddings after each round by rescaling pairwise distances. Whichever route you pick, keep logging the similarity curve: it tells you whether the fix actually worked, which accuracy alone will not.

  • How do you tell over-smoothing apart from vanishing gradients in a deep graph model?
    Measure both. Over-smoothing is a forward-pass property: gradient norms can be perfectly healthy and training loss can fall while node embeddings converge toward one another. Vanishing gradients show as tiny gradient norms in early layers and a training loss that barely moves. If similarity between embeddings is climbing toward 1 while gradients look fine, it is smoothing.
  • If accuracy drops from 2 to 8 layers, why isn't the obvious diagnosis overfitting?
    Overfitting widens the gap between training and validation accuracy while training accuracy stays high or improves. Over-smoothing usually depresses training accuracy too, because the representations reaching the head genuinely cannot separate the classes. Check the training curve first: if both curves fall together, more regularization is the wrong fix.
  • Does over-smoothing hurt graph-level tasks as much as node-level ones?
    Less directly, but it still hurts. A graph-level readout pools node embeddings anyway, so losing contrast between nodes matters less than when you classify each node. But once all nodes converge, the pooled vector carries little more than a degree summary, so two structurally different graphs can produce nearly identical readouts.

Stirring several colours of paint in one bucket. Two stirs and you still see the streaks; twenty and every spoonful is the same grey, no matter which corner you scoop from.

saying these in an interview costs you the question

  • Calling it vanishing gradients in disguise
  • Claiming more layers always add capacity
  • Diagnosing it as overfitting and adding dropout
  • Thinking it only appears on huge graphs
  • Believing nonlinearities prevent the collapse entirely
  • Judging depth by accuracy alone, never measuring embeddings

context

open as a page

How does over-squashing differ from over-smoothing in a graph neural network?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Over-smoothing is a loss of contrast: node representations converge as averaging rounds stack. Over-squashing is a loss of capacity in transit: an exponentially growing neighbourhood is funnelled through bottleneck edges into fixed-width vectors, so distant evidence never arrives intact.

open as a page

Your graph network must use evidence six hops away, but accuracy drops past three layers — how do you design for it?

level: principalimportance: should knowfreq 30%

basics

~20 s

Treat it as two problems: over-smoothing at depth and a reach problem. Make depth survivable with a jumping-knowledge readout and initial-residual connections, then shorten the distance itself by targeted rewiring or coarsening, re-measuring after each move.

open as a page