Lesson 2 · The Transformer

The Architecture at a Glance

In Lesson 1, each token was converted to a dense vector by looking up a row in the learned embedding matrix E, then a positional embedding Pt was added to mark its place in the sequence. That operation produces the transformer's actual input — one d-dimensional vector per token, stacked into a matrix:

Embeddings → Transformer input (from Lesson 1)x(0)t = E[idt] + Pt // token embedding + positional embedding Stack T tokens → X(0) ∈ ℝT×d // this matrix enters the transformer

The transformer's job is to refine X(0) into progressively richer representations by passing it through L successive blocks. Each block performs two operations: a self-attention layer (which lets every token gather information from every earlier token and itself) and a feedforward network (which processes each position independently). Every block reads from and writes back to these same vectors — the residual stream. Unlike a plain feedforward network — where each layer's output replaces the previous one — the residual stream works by addition: each block contributes a correction to the existing vectors, so the original token representation is not replaced and stays part of the sum at every depth (although later layers can add directions that cancel parts of it).

For GPT-2 small there are 12 such blocks, each operating on the same 768-dimensional vectors that the embedding lookup produced. The model applies those two operations 12 times before producing output logits. This block count is what practitioners mean by the model's depth: a 12-block transformer has depth 12 by the standard convention, or depth 24 if the attention and feedforward sublayers are each counted separately. When researchers refer to "layer N activations" or compare model depths, they almost always mean the block count.

Figure 1 — From Token IDs to Output Logits
Token IDs → E[idt] + Pt = X(0) ∈ ℝT×d
Embedding lookup + positional encoding (Lesson 1)
↓
× L blocks
Layer Norm
↓
Multi-Head Self-Attention
↕ residual connection (+ x)
Layer Norm
↓
Feedforward Network (MLP)
↕ residual connection (+ x′)
↓
Final Layer Norm
↓
LayerNorm(X(L)) → unembedding → output logits over vocabulary
The embedding vectors from Lesson 1 are the literal starting point (X(0)). Each transformer block refines them in place — adding information from earlier tokens via attention, then processing each position independently via the feedforward layer. After the last block, a final layer norm is applied and the result is projected through the unembedding matrix to produce next-token probabilities.
One transformer block (pre-norm convention)x′ = x + MHA(LayerNorm(x)) // attention sub-layer (multi-head attention, tab 4) with residual xout = x′ + FFN(LayerNorm(x′)) // feedforward sub-layer with residual

Notice what stays constant across all 12 blocks: the dimensionality d. Every block receives a T×d matrix and emits a T×d matrix. The embedding lookup fixes d, and the transformer never changes it. The blocks only refine the content of those vectors — not their shape. This is what makes the residual connection possible: each sublayer adds a correction of the same shape to the stream it reads from.

Key intuition: The embedding vectors from Lesson 1 are a first draft — each token represented in isolation, with no awareness of context. The transformer's blocks are a sequence of revisions: each pass lets every token incorporate information from its neighbors, progressively enriching the representation until it is rich enough to predict the next word.

Model scale: where do all the parameters go?

A 1.5B-parameter model like GPT-2 XL sounds abstract. Most of those parameters live in just two places per block: the attention projection matrices WQ, WK, WV, WO (each d × d, so 4d² per block), and the feedforward weight matrices Wup and Wdown (d × 4d and 4d × d, so another 8d² per block). That gives roughly 12d² parameters per block times L blocks — for GPT-2 XL that's 12 × 1,600² × 48 ≈ 1.5B (GPT-2 small: 12 × 768² × 12 ≈ 85M, plus ~39M of embeddings ≈ 124M).

Parameter budget per blockAttention (WQ, WK, WV, WO): 4 × d² // four d×d matrices Feedforward (Wup, Wdown): 8 × d² // d→4d→d, both directions ────────────────────────────────────────── Total per block: 12 × d² GPT-2 small (d=768, L=12): ~85M + embeddings ≈ 124M params GPT-2 XL (d=1600, L=48): ~1.5B params
Neuroscience parallel: The layered structure mirrors the hierarchical organization of sensory cortex — V1, V2, V4, IT in vision; A1, belt, parabelt in audition. Early layers extract local features; later layers build abstract, task-relevant representations. The difference is that transformer layers are identical in structure — the abstraction hierarchy emerges purely from training, not from anatomical specialization.

The Residual Stream

The residual stream is the sequence of d-dimensional vectors that passes through the entire model — one vector per token position. It starts as the sum of the token embedding and the positional embedding, and each subsequent block reads from it and writes an additive correction back to it.

At no point does any layer replace the stream. Attention adds a correction; the feedforward adds another correction. The original token embedding is still part of the sum at every layer — it has been incrementally refined, though later layers can write directions that partly cancel or crowd out what earlier layers wrote.

Figure 2 — The Residual Stream Through L Blocks
x(0) = E[id] + P x(1) = x(0) + Attn(0) + FFN(0) x(2) = x(1) + Attn(1) + FFN(1) x(l) x(l+1) = x(l) + Attn(l) + FFN(l) Block 0: Self-Attention Block 0: Feedforward Block 1: Self-Attention Block 1: Feedforward Block l: Self-Attention Block l: Feedforward ⊕ ⊕ ⊕
The residual stream (central vertical axis) carries the representation through all L blocks, numbered 0 to L−1. Blocks 0 and 1 show the pattern concretely; block l shows the general form (it reads x(l) and writes x(l+1)). Each block's self-attention sublayer (blue) and feedforward sublayer (orange) each compute a correction and write it to the stream (⊕). The stream is never replaced — only added to, so x(0) stays in the sum at every depth (later terms can still cancel parts of it).

Why residuals matter

Without residual connections, gradients vanish as they backpropagate through many layers — the product of many Jacobians approaches zero. Residuals solve this by providing a gradient highway: the loss gradient can flow back directly to early layers without passing through every transformation. This is the same insight behind ResNets in computer vision.

The residual formulation also has a useful interpretive consequence: a sublayer that learns nothing useful can simply output zero, so the block acts as the identity function and leaves the stream unchanged. This means the model can effectively decide how deep to process each token by tuning how much each block contributes.

Common misconception: It is tempting to think of the residual stream as a "working memory" that gets overwritten layer by layer. It isn't replaced wholesale — every layer's contribution stays in the sum, unless a later layer writes a direction that cancels it (which models do learn, for example to remove information they no longer need). Mechanistic interpretability research often exploits this, tracing how specific circuits write information in early layers and read it back in later ones.

The superposition hypothesis

The residual stream has d dimensions — 768 for GPT-2 small. But the model needs to track far more than 768 independent concepts simultaneously. Research on superposition suggests the model packs many more features into these dimensions by encoding them as near-orthogonal directions, accepting small interference between features as a tolerable cost. This is an active area of mechanistic interpretability research.

Neuroscience parallel: The residual stream resembles the concept of a population code in systems neuroscience — a large set of neurons jointly encoding many variables simultaneously, with each neuron responding to a mixture of features (mixed selectivity). Just as a single prefrontal neuron might encode task context, reward, and stimulus identity all at once, individual dimensions of the residual stream encode overlapping, distributed information.
Neuroscience parallel — network dynamics: The residual stream update rule (x(l+1) = x(l) + Δ(l)) is mathematically identical to an Euler step in a discrete dynamical system. This makes the residual stream a state-space trajectory: depth plays the role of time, and each layer applies a vector field that moves the representation toward something more useful for prediction. Neural ODE models (Chen et al., 2018) formalize this connection explicitly, treating network depth as a continuous time axis. The closer neuroscience analog is the ventral visual stream (V1→V2→V4→IT) — a spatial unfolding of representations across a processing hierarchy — rather than temporal oscillatory dynamics, since a transformer has no recurrence across time. The high-dimensional trajectory framing also connects naturally to superposition: just as neural populations traverse trajectories through high-dimensional activity spaces during a task, the residual stream navigates a high-dimensional representation space where many features are packed as near-orthogonal directions.

Self-Attention

Attention is the mechanism that lets every token position look at every earlier position (and itself) and decide how much information to gather from each. Unlike the feedforward layers, which process each position in isolation, attention computes pairwise relationships across the sequence.

Queries, Keys, and Values

Each position in the sequence generates three vectors from its current residual stream state: a Query Q (what information am I looking for?), a Key K (what information do I advertise?), and a Value V (what information do I actually contain?). These are computed by projecting x through three learned weight matrices.

Figure 3 — Computing Q, K, V
xt ∈ ℝd × WQ × WK × WV qt ks vs Query Key Value What am I seeking? What do I advertise? What do I contribute? scores other keys scored by other queries mixed into output three independent projections of the same xt ↓ scoring: for each pair of positions t (query) and s (key) qt · ks / √dk = score softmax → αt,s Σ αt,s · vs = outputt
One shared xt fans out to three independent projections, each with a distinct role. Below the separator: qt · ks scores how much position t attends to position s; softmax normalises scores into weights αt,s; and the weighted sum over vs produces the output for position t. The matrix operation QK⊤ computes all T² dot products simultaneously.
How Q, K, and V acquire meaning. The names Query, Key, and Value are borrowed from database retrieval — a useful analogy, but one the architecture does not enforce. The only structural constraint is this: Q and K are compared via dot product to produce attention scores, while V supplies the content that gets weighted and summed. Which features each projection captures — and whether they behave like "questions," "labels," and "answers" in any intuitive sense — is determined entirely by training. Gradient descent finds whatever assignment of roles minimises prediction loss. The semantic descriptions we attach to these projections are patterns observed in trained models, not properties specified in advance.
Attention computationQ = X WQ, K = X WK, V = X WV // project all positions at once S = Q K⊤ / √dk + mask // T×T score matrix (St,s = qt·ks/√dk) maskt,s = 0 if s ≤ t, −∞ if s > t // causal mask: no looking at later tokens A = softmax(S) // row-wise softmax → attention weights (e−∞ = 0) Output = A V // weighted sum of values

The dot product Q K⊤ produces a score for every (query, key) pair — how well position t's query matches position s's key. Dividing by √dk prevents the dot products from growing too large (which would push the softmax into regions of near-zero gradient). The softmax then converts scores into weights that sum to one per row.

Causal masking: During training and inference, a token at position t must not attend to future positions. This is enforced by setting the scores above the diagonal to −∞ before the softmax (which maps them to 0 weight). The model therefore sees a lower-triangular attention pattern — position t can only gather information from positions 0 through t (positions are numbered from 0).

The √dk scaling factor

The scaling by √dk is subtle but important. If q and k are dk-dimensional random vectors with unit-variance components, their dot product has variance dk (it's a sum of dk random terms). Dividing by √dk brings the variance back to one. Without this, large dot products would make the softmax extremely peaky — one position would receive nearly all the attention — which creates a gradient bottleneck.

Interactive: Softmax on Attention Scores

Edit the raw attention scores below to see how softmax converts them to probabilities. Notice how even a small score difference produces a large probability concentration.

Softmax Demo
Neuroscience parallel: The attention pattern — the matrix of αt,s values that determines how much each position attends to each other — resembles effective connectivity between brain areas: dynamic, context-dependent routing of information that changes trial by trial. The learned projection matrices WQ, WK, WV are the fixed-weight tracts; the attention pattern they produce is recomputed fresh for every new input. This is reminiscent of top-down attentional modulation in the visual cortex, where the strength of signal propagation from one area to another is gated by task demands.

Multi-Head Attention

A single attention head produces one dk-dimensional output per position. But a sentence has many kinds of structure simultaneously — syntactic dependencies, coreference relations, semantic roles, positional proximity. Running H parallel attention heads allows the model to attend to different types of relationships at once, each head learning its own Q/K/V projection matrices.

Each head reads the full d-dimensional stream and projects it, with its own WQ, WK, WV, into a smaller space of size dk = d / H. For GPT-2 small with d = 768 and H = 12 heads, each head works in its own 64-dimensional space — a learned projection of all 768 dimensions, not a slice of them. The outputs from all heads are concatenated and projected back to d dimensions.

MHA(X) (multi-head attention) is the whole attention sub-layer of one block written as a single function: it takes the stream X (T × d: one row per token) and returns an update of the same size, which is added to the stream. In GPT-2 its input is the layer-normed stream, so a block computes X′ = X + MHA(LayerNorm(X)) (tab 6).

Figure 4 — Multi-Head Attention
Input X ∈ ℝT×d
↓
↓ concatenate
Concat(head0, …, headH−1) ∈ ℝT×Hdk = ℝT×d
↓
× WO ∈ ℝd×d
↓
MHA output ∈ ℝT×d
Each head independently computes attention over the sequence in its own projected 64-dimensional space. Concatenation places the heads' outputs side by side, and WO maps them back to d dimensions; as the equations below show, this is the same as each head writing its own update and the updates being added.
Multi-head attentionAttention(Q, K, V) = softmax(Q K⊤ / √dk + mask) V // one head (tab 3); mask = −∞ above the diagonal headh = Attention(X WhQ, X WhK, X WhV) // each head h = 0 … H−1; T × dk MHA(X) = Concat(head0, …, headH−1) WO // join and project: T × d = head0 W0O + head1 W1O + … + headH−1 WH−1O // the same: a sum of the heads' writes WhQ, WhK, WhV ∈ ℝd×dk where dk = d/H WO ∈ ℝd×d; WhO ∈ ℝdk×d = rows h·dk … (h+1)·dk−1 of WO // biases (bQ, bK, bV, bO) omitted

The two forms of MHA(X) are equal because multiplying a concatenation by a matrix is the same as multiplying each piece by its own block of rows and adding: head h only ever meets rows h·dk to (h+1)·dk−1 of WO, its own WhO. So each head writes its own d-dimensional update, headh WhO, and the attention sub-layer's output is their sum (plus the bias bO). Heads in the same layer do not exchange information; they interact only through the stream, when a later layer reads what an earlier one wrote. Interpretability work uses this per-head form to ask what each head contributes.

SymbolMeaningSize (GPT-2 small)
Xthe (layer-normed) residual stream, one row per tokenT × 768
T, d, H, dktokens, stream width, heads per layer, head width (d / H)T, 768, 12, 64
WhQ, WhK, WhVhead h's query, key and value matrices (superscript = which head, subscript = which matrix)768 × 64 each
Q, K, Vone head's queries, keys and values: what each token looks for, offers, and passes onT × 64 each
headhhead h's output: at each position, the attention-weighted average of the valuesT × 64
WO, WhOoutput matrix of the layer; head h's block of 64 rows of it768 × 768; 64 × 768
MHA(X)the attention sub-layer's output, added to the streamT × 768

What do different heads specialize in?

Interpretability research has found that some attention heads develop recognisable functions. Much of the evidence for the first three types below comes from BERT, a bidirectional model (Clark et al., 2019); GPT-style models show similar heads, plus induction heads. Some well-documented head types include:

Syntactic heads — attend from a word to a grammatically related word, such as a direct object to its verb or a determiner to its noun; in BERT, some heads follow particular dependency relations with fairly high accuracy.
Positional heads — attend to the immediately preceding token regardless of content, effectively passing information one step along the sequence. (BERT also has heads that attend to the following token; a causal mask forbids this in GPT-style models.)
Coreference heads — link a pronoun or repeated mention back to an earlier mention of the same entity ("she" → "the scientist").
Induction heads
›

If the sequence contains "A B … A", two heads work together. First, a previous-token head in an earlier layer writes into B's position that B is preceded by A. Then, at the second A, the induction head looks for a position preceded by A, so it attends to B and copies B into the output — predicting that "A B" will repeat. Olsson et al. (2022) present preliminary evidence that these heads underlie much of in-context learning: the model's ability to pick up on patterns demonstrated earlier in the prompt (see Lesson 7, tab 5).

Importantly, no single head handles everything. The power comes from the ensemble — H heads each contributing a different "read" of the context, each mapped back to d dimensions by its block of WO, and added together into a single update to the residual stream.

Interactive: Head Specialization

The heatmap below shows attention weights for the same sentence across four hypothetical heads. Row t, column s shows how much position t attends to position s (upper-triangle cells are masked — causal attention only looks back). Switch heads to see the contrast: positional, syntactic, duplicate-token, and global patterns all emerge from the same architecture with different learned weights.

Self-Attention Heatmap — Head Specialization
Low attention
High attention

Neuroscience parallel: Multi-head attention is conceptually similar to parallel processing streams in sensory cortex — the ventral (what) and dorsal (where) visual pathways extract different features from the same retinal input simultaneously. In auditory cortex, pitch, timbre, and spatial location are processed in partially distinct pathways before being integrated. The key difference is anatomical: these cortical streams are physically separated, while attention heads are mathematical abstractions running in parallel on the same hardware.

Feedforward Layers and Layer Normalization

The Feedforward Network

After attention gathers information across positions, a position-wise feedforward network processes each token's vector independently. It is a two-layer MLP: expand from d to 4d dimensions, apply a nonlinearity, then project back to d. Despite its simplicity, the feedforward layer holds more parameters than the attention layer for most models (8d² vs 4d² per block).

Division of labor. Each transformer block alternates between two categorically different operations. Attention is the only place tokens communicate — it routes information across positions, assembling context. The feedforward network then operates on each position in isolation, with no awareness of neighboring tokens, transforming what attention assembled into a richer local representation. This alternation — gather, then process; gather, then process — repeats L times and is the core computational motif of the transformer.
Figure 5 — Feedforward Expansion and Compression
The input vector of dimension d is first expanded to 4d by the first linear layer, a nonlinearity is applied element-wise, then it is compressed back to d. This expansion-compression pattern can act as a kind of memory: research suggests each hidden unit works like a key–value pair, with the key responding to particular input patterns and the value promoting likely next tokens (Geva et al., 2021).
Feedforward networkFFN(x) = GELU(x Wup) Wdown // x is a row vector, as in attention Wup ∈ ℝd×4d // expand: d → 4d Wdown ∈ ℝ4d×d // compress: 4d → d

GPT-2-era models (GPT-2, GPT-3, BERT) use GELU (Gaussian Error Linear Unit) rather than ReLU; most recent models use the gated SwiGLU variant described below. GELU is smoother and approximates ReLU while keeping a nonzero gradient for almost all inputs (unlike ReLU's flat zero for x < 0). It is defined as x · Φ(x) where Φ is the standard normal CDF — in practice approximated as 0.5x(1 + tanh(√(2/π)(x + 0.044715x³))). For a detailed treatment of ReLU, GELU, and activation functions more broadly, see Lesson 1, tab 2.

Gated MLPs and Wgate

Many recent models — LLaMA, PaLM, Mistral — replace the two-matrix FFN with a gated variant that adds a third weight matrix, Wgate. Instead of applying the nonlinearity directly to x Wup, the hidden layer is element-wise multiplied (⊙) by a learned gate:

SwiGLU feedforward (gated)FFNSwiGLU(x) = ( x Wup ⊙ SiLU(x Wgate) ) Wdown Wup, Wgate ∈ ℝd×dff // both expand d → dff Wdown ∈ ℝdff×d // compress dff → d dff ≈ (8/3)d // LLaMA: 3·d·dff ≈ 8d², same as the 4d GELU FFN SiLU(z) = z · σ(z) // "Sigmoid Linear Unit" — smooth gate, ≈ 0 for z ≪ 0

The SiLU gate selectively opens or closes each hidden dimension based on the current input. Wgate learns which intermediate directions are worth passing through; Wup learns what content to project into those directions. The result is that the network has dynamic, input-dependent control over which "neurons" contribute — a richer computational motif than a fixed nonlinearity applied uniformly. Because the gate adds a third matrix, the hidden size is reduced from 4d to about (8/3)d (as in LLaMA) so the FFN keeps roughly 8d² parameters. At that matched parameter count SwiGLU outperforms plain GELU (Shazeer, 2020), which is why it is now the dominant FFN design in frontier models.

FFN as memory: Geva et al. (2021) found that the feedforward layers act like key-value memories. Wup columns are "keys": each fires on particular input patterns (shallow ones such as a shared last word in lower layers, more semantic ones in upper layers). Wdown rows are "values": what is written back to the residual stream when a key fires, which raises the probability of tokens that tend to follow that pattern. (An illustrative example: a key that fires on "The Eiffel Tower is in" could write a direction that promotes "Paris".) Later work links factual recall to such mid-layer FFN memories (Lesson 7, tab 7).

Layer Normalization

Before each sub-layer, a copy of the residual stream is normalized across its d dimensions to have zero mean and unit variance, then rescaled by learned parameters γ and β. This gives every attention and feedforward sublayer an input of consistent scale, however large the stream has grown — useful when composing dozens of transformations (24 sublayers in GPT-2 small, 96 in GPT-2 XL). Only the copy fed into the sublayer is normalized; the residual stream itself is not. Many recent models (Llama, Mistral) use RMSNorm, a simpler variant that skips the mean subtraction and the shift β.

Layer normalizationLayerNorm(x) = γ ⊙ (x − μ) / σ + β μ = mean(x) // mean over d dimensions σ = std(x) // std over d dimensions γ, β ∈ ℝd // learned scale and shift
Figure 6 — Layer Norm Step by Step
A 5-dimensional token vector walked through each arithmetic step. Note that γ and β restore the network's ability to express any mean and scale — LayerNorm does not lock representations to zero mean, it removes uncontrolled scale before reintroducing learned scale. Layer norm operates independently at each position, normalizing across the d feature dimensions (not across the sequence).

Pre-norm vs post-norm

The original "Attention Is All You Need" paper (Vaswani et al., 2017) placed layer norm after each sublayer (post-norm). Modern models — GPT-2, GPT-3, LLaMA — place it before (pre-norm). Pre-norm is easier to train at scale because it leaves a clean identity path: each sublayer's output is simply added to the stream, nothing normalizes the stream itself, and gradients pass straight back through the additions. Post-norm puts a layer norm on that path after every addition, which makes gradients near the output large at the start of training and calls for a careful learning-rate warm-up (Xiong et al., 2020). The price of pre-norm is that the stream's norm grows with depth, which is one reason a final layer norm is applied before the unembedding.

Neuroscience parallel: The FFN's expand–nonlinearity–compress structure (d → 4d → d) resembles the local circuit motif of a cortical column: inputs arrive at a position, are fanned out across a larger population of neurons (layer 4 → supragranular layers), a nonlinearity shapes how strongly each unit responds, and the result is projected back to a lower-dimensional output. Crucially, this processing is local — each token's FFN computation is independent of every other position, just as a cortical column's recurrent processing is largely confined to its own spatial neighborhood before long-range projections (the analog of attention) carry information across areas. Unlike ReLU, GELU has no hard threshold: negative inputs give small nonzero outputs, so the 4d units are not silenced, and their activity is graded and fairly dense. The closer analog of Olshausen & Field's sparse coding — cortex representing stimuli with a small fraction of active neurons — is found not in single units but in features: directions recovered by sparse autoencoders (Lesson 7, tab 8).

The Full Forward Pass

With the pieces in place — embeddings, residual stream, attention, feedforward, layer norm — we can trace exactly what happens to an input sequence from raw tokens to output logits. Step through each stage below.

1
Tokenization and Embedding Lookup
›

The input string is tokenized into T integer IDs. Each ID is used to select a row from the embedding matrix E ∈ ℝ|V|×d. A positional embedding Pt is added at each position.

Input: T token IDs

E ∈ ℝ|V|×d
→
X(0) ∈ ℝT×d

Each row of X(0) is the starting vector for that token position. All subsequent computation operates on these T vectors in parallel.

2
Layer Norm (pre-norm)
›

At each block, the residual stream is first normalized by LayerNorm (layer normalization, tab 5: each row centred, scaled to standard deviation 1, then given a learned scale and shift; not a logarithm). LayerNorm is applied independently at every position (row of X).

X(l) ∈ ℝT×d
→
LayerNorm(X(l)) ∈ ℝT×d

The normalized version is passed into the attention and feedforward sublayers. The original X(l) is retained for the residual connection.

3
Multi-Head Self-Attention
›

For each of H heads, Q, K, V are computed by linear projection. Attention weights A are formed as softmax(QK⊤/√dk) with causal masking applied. The attended values AV are computed, all H head outputs are concatenated, and projected by WO: the same as adding each head's own write, headh WhO, plus the bias bO (tab 4).

LayerNorm(X) → Q, K, V ∈ ℝT×dk per head

A = softmax(QK⊤/√dk) ∈ ℝT×T

MHA(LayerNorm(X)) ∈ ℝT×d

The attention computation has complexity O(T²d) — it scales quadratically with sequence length T, which is one motivation for efficient attention variants in long-context models.

4
Residual Addition (post-attention)
›

The attention output is added back to the original (pre-norm) residual stream. This is the first residual connection in the block.

X′ = X(l) + MHA(LayerNorm(X(l)))

X′ now contains the original information in X(l) plus contextual updates from attention. The feedforward layer will read from X′.

5
Feedforward Network (position-wise)
›

A second layer norm is applied to X′, then the feedforward MLP transforms each position's vector independently: expand d → 4d with Wup, apply GELU, compress back 4d → d with Wdown. A second residual connection adds this back to X′.

X(l+1) = X′ + FFN(LayerNorm(X′))

This completes one block. X(l+1) is the residual stream entering the next block. Steps 2–5 repeat for each of the L blocks.

6
Final Layer Norm and Unembedding
›

After the last block, a final layer norm is applied. The resulting T×d matrix is multiplied by the unembedding matrix — in GPT-2, the transpose of the embedding matrix E⊤ (weight tying; Pythia, Llama and Mistral learn a separate matrix instead) — producing logits over the vocabulary for each position.

X(L) → LayerNorm(X(L)) ∈ ℝT×d

logits = LayerNorm(X(L)) · E⊤ ∈ ℝT×|V|

P(next token | context) = softmax(logits[T−1])

When generating text, only the last position's logits are used to pick the next token; in training, every position's logits are scored against the token that follows it. The output is a probability distribution over all |V| tokens (50,257 for GPT-2).

Complete forward pass summaryX(0) = Embed(tokens) + PosEmbed // T × d for l = 0 to L−1: // block l maps X(l) → X(l+1) X′ = X(l) + MHA(LayerNorm(X(l))) // attention sub-layer X(l+1) = X′ + FFN(LayerNorm(X′)) // feedforward sub-layer logits = LayerNorm(X(L)) · E⊤ // T × |V| P = softmax(logits[T−1]) // next-token distribution (last position, at generation)
Everything is differentiable. Every operation in this forward pass — embedding lookup, matrix multiplications, layer norms, softmax, GELU — is differentiable with respect to the model parameters. This means the entire stack can be trained end-to-end by gradient descent, minimizing the cross-entropy loss between predicted and actual next tokens.