Attention is one part of a Transformer. This chapter builds the rest (the residual stream, normalization, the feed-forward network, and position) and then counts every parameter and every FLOP of the block that every large model is built from.
Chapter 5 · Section 5.1 · 40 min

The residual stream

Section 4.7 ended with a warning. A stack of pure attention layers loses rank doubly exponentially fast with depth, until every token carries nearly the same vector (Dong et al., 2021). Something has to carry each token's own information up through dozens of layers. You met the fix in §0.8, where it let ResNets train at 152 layers at a time when a plain 56-layer network had a higher training error than a 20-layer one (He et al., 2016). Instead of asking each layer to compute a new representation, ask it to compute a correction and add it to its input, x+f(x)\mathbf{x} + f(\mathbf{x}) instead of f(x)f(\mathbf{x}).

Every Transformer since 2017 is built on the same trick. In a Transformer it deserves a better name than "skip connection", because it changes how you should picture the whole model. The vector that gets corrected, layer after layer, is called the residual stream, and the rest of this chapter hangs off it.

Section 0.8 showed why the identity path keeps gradients from vanishing. This section goes further. We will see the stream as a running sum that every sublayer reads from and writes to, split a model's output exactly into per-layer contributions, and find that the same identity path lets gradients explode unless each branch shrinks with depth.

A block computes a correction, not a replacement

Write the TT token vectors of a sequence as the rows of X∈RT×d\mathbf{X} \in \R^{T \times d}, as in Chapter 4, where dd is the model width. A residual layer computes

X(ℓ+1)=X(ℓ)+fℓ(X(ℓ)),fℓ:RT×d→RT×d,\mathbf{X}^{(\ell+1)} = \mathbf{X}^{(\ell)} + f_\ell\big(\mathbf{X}^{(\ell)}\big), \qquad f_\ell : \R^{T\times d} \to \R^{T\times d},

where X(ℓ)\mathbf{X}^{(\ell)} is the stream before sublayer ℓ\ell and fℓf_\ell is the sublayer (an attention layer or a feed-forward network, each with its own parameters). The superscript (ℓ)(\ell) always means "after ℓ\ell sublayers". The stream starts as X(0)\mathbf{X}^{(0)}, the token embeddings (plus position information, which we add in §5.4).

In plain words, each sublayer looks at the current state of every token and proposes a change. The change is added, nothing is overwritten.

Two things follow immediately. First, if fℓf_\ell outputs zeros, the layer is exactly the identity. A deep residual network at initialization (where each fℓf_\ell is small) behaves like a shallow one, and depth is something the network grows into rather than something it must fight. That is the cure for the 56-layer puzzle. Second, the output of a block is the same shape as its input, T×dT \times d, always. That is why you can stack 12, 96, or 128 identical blocks without any glue.

A Transformer block contains two residual sublayers, attention followed by a feed-forward network (§5.3), so a model with LL blocks has 2L2L sublayers writing into the stream. In this section we count sublayers and write SS for their number, so S=2LS = 2L for a Transformer. Attention is the only place where tokens exchange information. The feed-forward network works on each token separately.

Unroll it, and the stream becomes a sum

Apply the update rule SS times and expand,

X(S)=X(0)+∑ℓ=0S−1fℓ(X(ℓ)).\mathbf{X}^{(S)} = \mathbf{X}^{(0)} + \sum_{\ell=0}^{S-1} f_\ell\big(\mathbf{X}^{(\ell)}\big).

In plain words, the final representation of every token is its embedding plus the sum of everything every sublayer ever wrote.

Here is a tiny example you can check by hand. Take d=3d = 3 and one token with embedding (1,0,0)(1, 0, 0). The first sublayer writes (0,0.5,0)(0, 0.5, 0), the second writes (0,0,0.2)(0, 0, 0.2), and the third writes (−0.3,0,0)(-0.3, 0, 0). The stream goes (1,0,0)→(1,0.5,0)→(1,0.5,0.2)→(0.7,0.5,0.2)(1, 0, 0) \to (1, 0.5, 0) \to (1, 0.5, 0.2) \to (0.7, 0.5, 0.2). Nothing is lost. You could read off the third layer's write from the difference of two consecutive states, and an earlier write is still sitting in the final vector unless a later layer deliberately subtracts it.

The widget below makes this concrete for a toy model with six sublayers and an 8-dimensional stream. Each dimension's bar is stacked from the contributions of every component that has written so far, colored by who wrote it.

What does it mean that the residual stream is a running sum?
Each bar is one of 8 stream dimensions, stacked from the pieces written by the embedding (gray) and each sublayer (colored). Switch sublayers off, rescale every write, and slide the readout depth to read the stream partway through.
Loading interactive figure…

Switching a layer off removes its color and, in this toy, also changes what later layers read, because each later write depends on the stream it sees. The logit change is therefore its direct share plus an indirect effect through later layers. Keep that distinction in mind. It is the difference between direct and total effects, and interpretability researchers fight over it constantly.

Let's build the same thing in NumPy. Each sublayer here is a stand-in (a random matrix and a tanh) rather than real attention, but the bookkeeping is identical.

Python · cell 1
Warm-up

Run a residual stream and keep the receipts

Write run_stream(X0, blocks) where X0 has shape (T, d) and blocks is a list of functions, each mapping a (T, d) array to a (T, d) write. Return (states, writes), where states has shape (S+1, T, d) with states[0] = X0 and states[l+1] = states[l] + blocks[l](states[l]), and writes has shape (S, T, d). Do not modify X0.

Hidden tests, hints, and AI help, from $1.99 a month.

Reading and writing, the stream as a shared channel

Look at what a sublayer actually does with the stream. It never sees "the previous layer's output" as a separate object. It sees the sum. An attention layer reads the stream through its query, key, and value projections WQ,WK,WV∈Rd×d\mathbf{W}_Q, \mathbf{W}_K, \mathbf{W}_V \in \R^{d \times d} and writes back through its output projection WO∈Rd×d\mathbf{W}_O \in \R^{d \times d}. The feed-forward network reads through its first matrix and writes through its second. Every read is a linear projection of the stream (after a normalization, §5.2), and every write is a vector added to it.

Elhage et al. (2021) turned this observation into a way of thinking that has shaped interpretability research ever since. The residual stream is a communication channel. Sublayers do not talk to each other directly. They leave messages in the stream, in some subspace, and later sublayers pick them up by projecting onto that subspace. Three consequences are worth having in your head.

Composition is a product of matrices. Suppose sublayer aa writes h Wout(a)\mathbf{h}\,\mathbf{W}_{\text{out}}^{(a)} into the stream (with h\mathbf{h} its internal activation) and a later sublayer bb reads x Win(b)\mathbf{x}\,\mathbf{W}_{\text{in}}^{(b)}. The part of bb's input that came from aa is h Wout(a)Win(b)\mathbf{h}\,\mathbf{W}_{\text{out}}^{(a)}\mathbf{W}_{\text{in}}^{(b)}. The product Wout(a)Win(b)\mathbf{W}_{\text{out}}^{(a)}\mathbf{W}_{\text{in}}^{(b)} is a "virtual weight" that connects the two sublayers directly, even though they may be twenty layers apart. This is how attention heads in different layers cooperate, for example in the induction heads previewed in §4.7.

The direct path is a model too. Set every fℓf_\ell to zero. What remains is embedding followed by unembedding, logits =x(0)WU= \mathbf{x}^{(0)}\mathbf{W}_U with WU∈Rd×V\mathbf{W}_U \in \R^{d \times V} the unembedding matrix. That zero-layer model can only use the current token to predict the next, so the best it can learn is bigram statistics. A trained Transformer keeps a version of this bigram table in the product EWU\mathbf{E}\mathbf{W}_U of its embedding and unembedding matrices, and every layer adds refinements on top of it.

Bandwidth is limited. All SS sublayers share the same dd dimensions. GPT-2 small has d=768d = 768 and 24 sublayers, many of which compute far more than 768 internal features. The stream cannot give each feature its own axis, so models store more features than dimensions by packing them into nearly orthogonal directions, the high-dimensional trick from §1.3. This is the setting for superposition, where a model represents more concepts than it has neurons. Elhage et al. also observed sublayers whose writes appear to erase information that is no longer needed, a kind of memory management.

Decomposing the output, exactly

Because the stream is a sum, the final logits are almost a sum too. The "almost" is the final normalization. GPT-style models compute logits as LN⁡(x(S)) WU\operatorname{LN}(\mathbf{x}^{(S)})\,\mathbf{W}_U, where for one token x∈Rd\mathbf{x} \in \R^{d}

LN⁡(x)=γ⊙x−μ1s+β,μ=1d∑jxj,s=1d∑j(xj−μ)2+ϵ.\operatorname{LN}(\mathbf{x}) = \boldsymbol{\gamma} \odot \frac{\mathbf{x} - \mu\mathbf{1}}{s} + \boldsymbol{\beta}, \qquad \mu = \frac{1}{d}\sum_{j} x_j, \quad s = \sqrt{\tfrac{1}{d}\textstyle\sum_j (x_j - \mu)^2 + \epsilon}.

Here γ,β∈Rd\boldsymbol{\gamma}, \boldsymbol{\beta} \in \R^d are a learned gain and shift, 1\mathbf{1} is the all-ones vector, and ϵ\epsilon is a small constant (§5.2 derives all of this properly). The mean subtraction is linear in x\mathbf{x}. The division by ss is not, but ss is a single number per token. If we treat ss as fixed for the token we are explaining, the logit of vocabulary item vv splits exactly into one term per component c\mathbf{c} of the stream (the embedding and every write),

zv=∑c(γ⊙c−mean⁡(c)1s)⋅(WU):,v  +  β⋅(WU):,v.z_v = \sum_{\mathbf{c}} \Big(\boldsymbol{\gamma} \odot \frac{\mathbf{c} - \operatorname{mean}(\mathbf{c})\mathbf{1}}{s}\Big)\cdot(\mathbf{W}_U)_{:,v} \;+\; \boldsymbol{\beta}\cdot(\mathbf{W}_U)_{:,v}.

In plain words, center each write, scale it by the shared 1/s1/s and the gain, and project it onto the unembedding column of the token you care about. That number is the write's direct contribution to the logit. This is called direct logit attribution, and it is the first tool people reach for when asking "which layer made the model say Paris?".

The same picture gives the logit lens (nostalgebraist, 2020). Apply the final normalization and the unembedding to an intermediate state x(ℓ)\mathbf{x}^{(\ell)} instead of x(S)\mathbf{x}^{(S)}, and you get the model's current best guess partway through. In trained models those guesses sharpen layer by layer, and the logit lens has become one of the basic tools for reading a model from the inside.

Python · cell 2

The two numbers agree to every printed digit. The decomposition is not an approximation once ss is frozen. What it does not capture is that a write also changes what later layers read, which is the indirect effect you saw in the widget.

Core

Direct logit attribution through a final LayerNorm

Write logit_attribution(parts, gamma, beta, W_U, v, eps=1e-5). parts has shape (C, d) and holds every component of one token's final stream (the embedding first, then each write), so the stream is parts.sum(0). Compute the token's LayerNorm statistics mu and s from that sum, then return (contrib, bias_term) where contrib[c] is component c's direct contribution to logit v (as in the formula above) and bias_term is beta @ W_U[:, v]. The contributions plus the bias term must equal the true logit.

Hidden tests, hints, and AI help, from $1.99 a month.

Gradients ride the identity

Now the reason residual networks train at all, redone for a stack of SS sublayers so that we can see how depth enters. Take one token's stream x(ℓ)∈Rd\mathbf{x}^{(\ell)} \in \R^d and the Jacobian of one sublayer, Jℓ=∂fℓ/∂x(ℓ)∈Rd×d\mathbf{J}_\ell = \partial f_\ell / \partial \mathbf{x}^{(\ell)} \in \R^{d \times d} (we use the column convention of §0.2, entry (i,j)(i,j) is ∂fi/∂xj\partial f_i/\partial x_j). Differentiate the update rule,

∂x(ℓ+1)∂x(ℓ)=I+Jℓ,∂x(S)∂x(ℓ)=(I+JS−1)(I+JS−2)⋯(I+Jℓ).\frac{\partial \mathbf{x}^{(\ell+1)}}{\partial \mathbf{x}^{(\ell)}} = \mathbf{I} + \mathbf{J}_\ell, \qquad \frac{\partial \mathbf{x}^{(S)}}{\partial \mathbf{x}^{(\ell)}} = (\mathbf{I} + \mathbf{J}_{S-1})(\mathbf{I} + \mathbf{J}_{S-2})\cdots(\mathbf{I} + \mathbf{J}_\ell).

Multiply out the product and the first term is I\mathbf{I}. Then come the sums of single Jacobians, then pairs, and so on,

∂x(S)∂x(ℓ)=I+∑kJk+∑k′>kJk′Jk+⋯+JS−1⋯Jℓ.\frac{\partial \mathbf{x}^{(S)}}{\partial \mathbf{x}^{(\ell)}} = \mathbf{I} + \sum_{k} \mathbf{J}_k + \sum_{k' > k} \mathbf{J}_{k'}\mathbf{J}_k + \cdots + \mathbf{J}_{S-1}\cdots\mathbf{J}_\ell .

Backpropagation sends the row vector g(S)=∂L/∂x(S)\mathbf{g}^{(S)} = \partial \mathcal{L}/\partial \mathbf{x}^{(S)} down by multiplying on the right, g(ℓ)=g(ℓ+1)(I+Jℓ)\mathbf{g}^{(\ell)} = \mathbf{g}^{(\ell+1)}(\mathbf{I} + \mathbf{J}_\ell). So

g(ℓ)=g(S)+(terms that pass through one or more sublayers).\mathbf{g}^{(\ell)} = \mathbf{g}^{(S)} + \text{(terms that pass through one or more sublayers)}.

In plain words, every layer receives the loss gradient at the top, untouched, plus whatever the sublayers above add to it. In a plain network x(ℓ+1)=fℓ(x(ℓ))\mathbf{x}^{(\ell+1)} = f_\ell(\mathbf{x}^{(\ell)}), the gradient is only the last term, a product of S−ℓS - \ell Jacobians, and products of many matrices shrink or blow up exponentially.

How fast? Here is a calculation you can do in an interview. Model each Jacobian as a random matrix with independent entries N(0,α2/d)\mathcal{N}(0, \alpha^2/d), so it scales a vector by about α\alpha (formally E∥gJ∥2=α2∥g∥2\mathbb{E}\lVert\mathbf{g}\mathbf{J}\rVert^2 = \alpha^2\lVert\mathbf{g}\rVert^2). For one residual step,

E ∥g(I+J)∥2=∥g∥2+2 E[gJg⊤]+E∥gJ∥2=(1+α2) ∥g∥2,\mathbb{E}\,\lVert \mathbf{g}(\mathbf{I} + \mathbf{J})\rVert^2 = \lVert\mathbf{g}\rVert^2 + 2\,\mathbb{E}[\mathbf{g}\mathbf{J}\mathbf{g}^\top] + \mathbb{E}\lVert\mathbf{g}\mathbf{J}\rVert^2 = (1 + \alpha^2)\,\lVert\mathbf{g}\rVert^2,

because the cross term has mean zero. After SS independent steps the gradient's root-mean-square size is (1+α2)S/2(1+\alpha^2)^{S/2} for the residual network and αS\alpha^S for the plain one.

The plain network vanishes for any α<1\alpha < 1 and explodes for any α>1\alpha > 1. Only the knife edge α=1\alpha = 1 survives, and real nonlinearities (a ReLU zeroes half its inputs) knock you off it. The residual network can never vanish, since (1+α2)≥1(1 + \alpha^2) \ge 1. But look carefully, it can explode, (1+α2)S/2≈eα2S/2(1 + \alpha^2)^{S/2} \approx e^{\alpha^2 S/2}. The way out is to keep each branch small in proportion to depth. With α2=1/S\alpha^2 = 1/S the growth is (1+1/S)S/2→e1/2≈1.65(1 + 1/S)^{S/2} \to e^{1/2} \approx 1.65 no matter how deep the model is. Remember that 1/S1/\sqrt{S}, because it comes back as the GPT-2 initialization rule in §5.7, where S=2LS = 2L gives a factor of 1/2L1/\sqrt{2L}.

Python · cell 3

At 64 layers, the plain network's gradient at α=0.5\alpha = 0.5 is about 10−2010^{-20}, numerically dead. The residual network's never drops below 1, but at α=1\alpha = 1 it is about 10910^{9}, which is why nobody trains a deep residual network with full-size branches. At α=1/S\alpha = 1/\sqrt{S} it sits near 1.6, matching the theory.

Interview

Backpropagate through a stack, in the right order

You are given the top gradient g_top (a vector of shape (d,)) and the sublayer Jacobians Js, an array of shape (S, d, d) where Js[l] is ∂fℓ/∂x(ℓ)\partial f_\ell/\partial \mathbf{x}^{(\ell)} in the column convention. Write backprop_stack(g_top, Js, residual=True) returning G of shape (S+1, d) with G[S] = g_top and G[l] the gradient with respect to x(ℓ)\mathbf{x}^{(\ell)}. For a residual stack g(ℓ)=g(ℓ+1)(I+Jℓ)\mathbf{g}^{(\ell)} = \mathbf{g}^{(\ell+1)}(\mathbf{I} + \mathbf{J}_\ell), and for a plain stack g(ℓ)=g(ℓ+1)Jℓ\mathbf{g}^{(\ell)} = \mathbf{g}^{(\ell+1)}\mathbf{J}_\ell.

Interviewers like this one because it has two classic traps, the order of the loop and the side the vector multiplies on.

Hidden tests, hints, and AI help, from $1.99 a month.

The forward signal grows too

The same arithmetic applies on the way up. If each write were a random linear function of the stream, ∥x(S)∥2\lVert\mathbf{x}^{(S)}\rVert^2 would grow like (1+α2)S(1 + \alpha^2)^S, exponentially. Real Transformers avoid that by normalizing what each sublayer reads (the pre-LN arrangement of §5.2), so each write has a roughly fixed size no matter how large the stream has become. Then the writes add like independent random vectors and the squared norm grows linearly, ∥x(S)∥2≈∥x(0)∥2+S c\lVert\mathbf{x}^{(S)}\rVert^2 \approx \lVert\mathbf{x}^{(0)}\rVert^2 + S\,c for a per-write squared size cc. Linear growth is survivable, but it has consequences. The later a sublayer sits, the smaller its write is relative to the stream, and the final normalization must divide by a number that grows like S\sqrt{S}. Section 5.2 shows how this shapes the gradients, and §5.7 how initialization keeps it in check.

A residual network is an ensemble of paths

Go back to the expanded product, I+∑Jk+∑Jk′Jk+⋯\mathbf{I} + \sum \mathbf{J}_k + \sum \mathbf{J}_{k'}\mathbf{J}_k + \cdots. Each term corresponds to a path from layer ℓ\ell to the top that passes through some subset of the sublayers and skips the rest. With SS sublayers there are 2S2^S paths, and (Sk)\binom{S}{k} of them pass through exactly kk sublayers.

Veit, Wilber & Belongie (2016) took this "unraveled" view seriously. If each sublayer on a path multiplies the gradient by a typical factor α\alpha, then the total contribution of length-kk paths is proportional to (Sk)αk\binom{S}{k}\alpha^k. Normalizing by ∑k(Sk)αk=(1+α)S\sum_k \binom{S}{k}\alpha^k = (1 + \alpha)^S (the binomial theorem) gives a distribution over path lengths with mean

E[k]=S α1+α.\mathbb{E}[k] = \frac{S\,\alpha}{1 + \alpha}.
∂ Where the mean comes from

Let Z(α)=∑k=0S(Sk)αk=(1+α)SZ(\alpha) = \sum_{k=0}^{S}\binom{S}{k}\alpha^k = (1+\alpha)^S. Differentiating term by term, αZ′(α)=∑kk(Sk)αk\alpha Z'(\alpha) = \sum_k k\binom{S}{k}\alpha^k. So

E[k]=∑kk(Sk)αkZ(α)=αZ′(α)Z(α)=αS(1+α)S−1(1+α)S=Sα1+α.\mathbb{E}[k] = \frac{\sum_k k\binom{S}{k}\alpha^k}{Z(\alpha)} = \frac{\alpha Z'(\alpha)}{Z(\alpha)} = \frac{\alpha S (1+\alpha)^{S-1}}{(1+\alpha)^S} = \frac{S\alpha}{1+\alpha}.

This is the mean of a binomial distribution with SS trials and success probability p=α/(1+α)p = \alpha/(1+\alpha), which is exactly what the normalized weights (Sk)pk(1−p)S−k\binom{S}{k}p^k(1-p)^{S-k} are.

In plain words, when sublayers shrink the gradient (α<1\alpha < 1), most of the gradient travels along paths that use only a fraction α/(1+α)\alpha/(1+\alpha) of the layers. Veit et al. measured this in a 110-layer ResNet and found that most of the gradient came from paths only 10 to 34 layers deep. They also found that deleting a single block from a trained ResNet at test time barely hurts accuracy, while deleting a layer from a plain VGG network destroys it. The network behaves less like one very deep function and more like a large ensemble of shallower ones that share weights.

Which paths through a residual network carry the gradient?
A stack of S residual sublayers unrolls into 2^S paths. If each sublayer on a path scales the gradient by alpha, paths of length k carry a share proportional to C(S, k) alpha^k. Slide depth and alpha.
Loading interactive figure…

Large language models show a version of the same robustness. Gromov et al. (2024) removed large fractions of the deepest layers of open models with modest loss on question-answering benchmarks after a small amount of fine-tuning. This is an empirical finding, and it is double-edged. It suggests that deep layers in today's pre-LN models are underused, which is part of the motivation for the depth-aware normalization and scaling tricks in §5.2 and §5.7.

Core

The path-length distribution, without overflow

Write path_length_weights(S, alpha) returning (w, mean), where w has shape (S+1,) with w[k] proportional to (Sk)αk\binom{S}{k}\alpha^k and summing to 1, and mean is ∑kk wk\sum_k k\,w_k. It must work for S = 2000 and alpha = 1.5, where (1+α)S(1+\alpha)^S overflows a float.

Hidden tests, hints, and AI help, from $1.99 a month.

In PyTorch

In PyTorch the residual add is one line, and forward hooks let you record every write without touching the model's code. This is how interpretability tooling captures the stream.

🔥 In PyTorchfor a machine with PyTorch

Plain, highway, residual

Residual connections were not the only proposal for training deep networks. Highway networks (Srivastava, Greff & Schmidhuber, 2015) came first, with a learned gate that mixes the input and the transformation.

connectionupdateidentity at init?gradient pathused in
plainx←f(x)\mathbf{x} \leftarrow f(\mathbf{x})noproduct of Jacobians onlyearly deep nets, VGG
highwayx←t⊙f(x)+(1−t)⊙x\mathbf{x} \leftarrow \mathbf{t}\odot f(\mathbf{x}) + (1-\mathbf{t})\odot\mathbf{x}, gate t\mathbf{t} learnedonly if the gate starts closedidentity scaled by 1−t1 - \mathbf{t}early very deep feedforward nets (2015)
residualx←x+f(x)\mathbf{x} \leftarrow \mathbf{x} + f(\mathbf{x})yes, if ff starts smallexact identity plus branchesResNets, every Transformer
scaled residualx←x+a f(x)\mathbf{x} \leftarrow \mathbf{x} + a\,f(\mathbf{x}), aa small or learnedyesidentity plus damped branchesReZero, DeepNet, GPT-2 init (§5.7)
densex←[x,f(x)]\mathbf{x} \leftarrow [\mathbf{x}, f(\mathbf{x})]yesidentity via concatenationDenseNet (width grows with depth)

The residual form won because the identity path is exact and free. A highway gate can close, and concatenation makes the width grow with every layer, which a 96-layer Transformer cannot afford.

Read more

Watch next

🎬 A Walkthrough of A Mathematical Framework for Transformer Circuits · Neel Nanda · starts at 26:10Nanda explains why the residual stream is the central object of the circuits view.
🎬 Let's build GPT: from scratch, in code, spelled out. · Andrej Karpathy · starts at 86:48Karpathy adds residual connections to a small Transformer and shows the effect on training.