The residual stream

Every token carries one vector up through the model. Each attention layer and each MLP reads that vector, computes something, and adds the result back. Nothing is overwritten. This running sum is the residual stream, and it is why deep transformers can be trained at all.

Key idea
x ← x + attention(x), then x ← x + MLP(x), repeated in every layer
Real world
A shared whiteboard in a meeting room. Each person who walks in reads what is there, adds a note, and leaves. Nobody rubs anything out, so the last person sees everyone’s notes at once.
In an LLM
At the last “the” of “The cat sat on the”, the embedding writes “this is the word the”, an attention head adds “it follows on”, another adds “the story is about a cat”, and an MLP adds “floor, mat or bed comes next”. The output layer reads the sum.

Two lines of code

Strip away the details and a transformer layer is two lines:

x←x+Attention⁡(x),x←x+MLP⁡(x)x \leftarrow x + \operatorname{Attention}(x), \qquad x \leftarrow x + \operatorname{MLP}(x)

Here xx is one token’s vector (768 numbers in GPT-2 small). Attention (the previous section) moves information between tokens; the MLP processes each token on its own. The important symbol is the plus. Neither layer replaces xx. Each one computes a change and adds it on. The vector that flows from the embedding at the bottom to the output at the top, collecting all these additions, is the .

“Residual” is the name for the thing each layer adds: the change, not the whole new vector. The idea comes from image recognition: He et al., 2015 found that a network where each layer adds a residual can be trained 100 layers deep or more, while a plain stack of the same depth trains worse than a shallow one.

A shared bus

Think of the residual stream as a bus, or a shared whiteboard, that runs past every component. Each component:

  1. reads the current vector (in practice it reads a normalised copy, see normalization),
  2. computes something from it,
  3. writes by adding its result back.

Because they all write to the same place, a later layer can read what any earlier layer wrote. An attention head in layer 5 can use a fact an MLP found in layer 2. Step through it:

embedding
x =e+a₁+m₁+a₂+m₂
word is “the”e1.0
small worde0.8
follows “on”
story: a cat
next: a place
next: floor/mat
embeddingattention writesMLP writes▸ read by this step
e: embedding
The embedding table writes the token’s starting meaning: this is the word “the”, a small word.
The stream starts as the token’s embedding. Each component that follows reads this vector, computes something, and adds its result back.
A cartoon of the residual stream at the last token of “The cat sat on the”. Real models have 768 to 16,384 unnamed dimensions; these six are made readable. Press play, or step with the arrows.

The dimensions in this cartoon have names so you can read them. In a real model they don’t: the 768 numbers are not labelled, and a single fact is usually spread over many of them as a direction in the space. But the bookkeeping is exactly this: start from the embedding, add, add, add.

Written out for a model with NN layers, the final vector is literally a sum:

xfinal=e⏟embedding+∑l=1N(al+ml)x_{\text{final}} = \underbrace{e}_{\text{embedding}} + \sum_{l=1}^{N} \big(a_l + m_l\big)

where ala_l and mlm_l are what attention and the MLP in layer ll wrote. This is why interpretability researchers can ask “which layer contributed this prediction?”: you can take the sum apart.

example · a shared whiteboard

A team plans a trip on one whiteboard. The first person writes the destination. The second reads it and adds the train times. The third reads both and adds “book the 9:15, it’s cheapest”. Nobody wipes the board, so the last person can see the destination, the times and the recommendation together, and also who wrote what. If someone’s note is useless, it just sits there; it doesn’t destroy anything.

example · “The cat sat on the”

The embedding of the last “the” only knows it is the word “the”. A previous-token head adds “follows on”. A head that looks for the subject adds information copied from “cat”. An MLP that has learned “on the + a place” writes a push towards place words. By the top, the vector at that position contains enough to give “ floor”, “ bed” and “ couch” high scores, which is what GPT-2 really predicts.

Measured in GPT-2

Here is the real thing. The top chart is the length (the norm) of one token’s residual vector after every attention and MLP step in GPT-2 small. The bars below are the lengths of what each layer wrote.

Loading GPT-2 data…
GPT-2 small’s residual stream, measured.

Three things stand out:

  • It grows. Every token starts as a vector of length about 5 and ends at several hundred. Since layers only add, the stream accumulates.
  • Late layers write the most. The early and middle layers make small, careful edits. The last two layers write much bigger vectors: they are shaping the final prediction.
  • The first token is strange. Pick “The” in any sentence. GPT-2 writes a vector of length about 3,000 there in its first three layers (mostly the MLPs of layers 1 and 2), leaves it nearly alone, and the attention of the last layer then cancels most of it. Many attention heads use the first token as a resting place when they have nothing better to attend to (an “attention sink”, see attention patterns), and this huge vector is part of how that works.

Because the stream keeps growing, every layer reads a normalised copy of it rather than the raw vector. Otherwise the late layers would see vectors several times longer than the early layers did, and every layer would have to cope with a different scale. That is the job of the next page, normalization.

Why the plus makes deep models trainable

Training adjusts each weight using its gradient: how much the loss would change if that weight changed. The gradient is computed backwards from the loss through every layer (backpropagation).

In a plain stack, xl+1=f(xl)x_{l+1} = f(x_l), the gradient reaching layer 1 is a product of one factor per layer. Multiply 48 numbers that are each a bit below 1 and you get almost nothing; a bit above 1 and it explodes. Early layers either stop learning or blow up.

With a residual, xl+1=xl+f(xl)x_{l+1} = x_l + f(x_l). The derivative of xl+1x_{l+1} with respect to xlx_l is 1+f′(xl)1 + f'(x_l): there is always a “1” in it, a path where the gradient passes straight through unchanged. Stack NN layers and there is a clean path from the loss all the way down to the embedding. Here is a simulated 16-wide network with and without the plus. Press play and watch the gradient travel down from the loss:

reached layer 0
plain: x ← tanh(Wx)residual: x ← x + tanh(Wx)
plain, at layer 03.9e-8
residual, at layer 03.0e+0
ratio8e+7×
In the plain stack the gradient reaching layer 0 is 3.9e-8: each layer multiplied it by something below 1, 32 times. The first layers would barely learn. With residuals the identity path adds the gradient straight through, and it arrives at 3.02.
A 16-wide toy network with tanh layers and random weights, simulated in your browser. The gradient starts at size 1 at the top and is passed down one layer at a time. Press play to watch it travel; compare the plain stack with the residual one.

The same widget appears again in backpropagation, where the chain rule behind it is worked through.

It also means a new layer starts life doing almost nothing harmful. With small initial weights, f(x)f(x) is close to zero and the layer is close to the identity. Training then teaches it to add something useful. A deep model is never worse at the start than a shallow one, which is the problem residuals were invented to fix.

going deeper

In code

class Block(nn.Module):
    def __init__(self, d, n_heads):
        super().__init__()
        self.ln1, self.ln2 = nn.LayerNorm(d), nn.LayerNorm(d)
        self.attn = CausalSelfAttention(d, n_heads)
        self.mlp = MLP(d)
 
    def forward(self, x):                 # x: (batch, T, d)
        x = x + self.attn(self.ln1(x))    # read a normalised copy, add back
        x = x + self.mlp(self.ln2(x))
        return x

Gradient through a residual

For xl+1=xl+fl(xl)x_{l+1} = x_l + f_l(x_l),

∂xN∂xl=∏k=lN−1(I+∂fk∂xk)=I+∑k∂fk∂xk+…\frac{\partial x_N}{\partial x_l} = \prod_{k=l}^{N-1} \Big(I + \frac{\partial f_k}{\partial x_k}\Big) = I + \sum_k \frac{\partial f_k}{\partial x_k} + \dots

The identity term II survives however deep the stack is.

In papers

Related

  • normalization - Before each attention layer and each MLP, the model rescales the token’s vector to a standard size. LayerNorm subtracts the mean and divides by the standard deviation; RMSNorm just divides by the root mean square. Where the norm sits, before the layer or after it, decides whether a deep model trains.
  • mlp - After attention has moved information between tokens, the MLP processes each token on its own: widen the vector four times, bend it with an activation function, narrow it back. Its neurons act like key–value memories, and it holds most of the model’s parameters.
  • the-block - Put the pieces together: LayerNorm, attention, add; LayerNorm, MLP, add. That is one transformer block, and a model is a stack of identical blocks between an embedding table and an output layer. Here is one block computed number by number, and an exact parameter count for real models.
  • backprop - To train, the model needs to know how each of its weights affected the loss. Backpropagation gets all of those gradients in one backward sweep using the chain rule. The residual stream gives the gradient a straight road down through the stack, and an optimiser such as Adam, with a warm-up and decay schedule, turns gradients into updates.