Quick review from Lesson 2
Before tracing the full forward pass, here are the four building blocks from the previous lesson. Each block operates on the residual stream — a sequence of d-dimensional vectors, one per token position — updating it additively.
x(l+1) = x(l) + Δ(l)
A = softmax(QK⊤/√dk), Out = AV
FFN(x) = GELU(x Wup + bup) Wdown + bdown
LN(x) = γ · (x − μ)/σ + β
What's new in this lesson
Three mechanisms that weren't covered in Lesson 2 are central to how a trained model actually runs:
The complete forward pass
Step through all eleven stages of a transformer forward pass. The architecture diagram on the left highlights the active component; the panel on the right shows its equation, tensor shape, and role.
Example input: "The cat sat on" — four tokens, model dimension d = 768, vocabulary |V| = 50,257.
Causal masking
Inside each attention head, every token computes a score against every other token. Without a constraint, token 3 could attend to token 5 — using information it hasn't "seen" yet. Causal masking prevents this.
How the mask works
The raw score matrix S ∈ ℝT×T is computed first — a float for every (query, key) pair. Then the upper triangle (future positions: key position s > query position t) is set to −∞. Softmax maps −∞ → 0, so those positions receive exactly zero attention weight.
Mt,s = St,s + maskt,s where maskt,s = 0 if s ≤ t, else −∞
A = softmax(M) ← rows sum to 1 over attended positions only
Interactive score matrix
Six-token sequence: "The cat sat on the mat". Toggle between the three states the score matrix passes through inside an attention head.
Why this is necessary
During training, the model predicts the next token at every position simultaneously. The loss at position 3 uses the model's prediction for token 4; that prediction must be made from tokens 0–3 only, not from tokens 4+ (which haven't been "read" yet in sequential generation). Without the mask, the model could simply "look up" the answer from the future context, learning nothing useful.
Encoder vs decoder attention
BERT-style encoder models use bidirectional attention — no causal mask. Every token can attend to every other token. This is valid when the task is understanding an existing sequence (classification, extraction), not generating new tokens. GPT-style decoders always use causal masking because they generate left-to-right.
Weight tying
After the final layer norm, the model has a matrix X̂(L) ∈ ℝT×d — one d-dimensional vector per token position. To produce next-token probabilities, these vectors must be projected into vocabulary space (|V| ≈ 50,000 entries). This projection is called unembedding.
The shared matrix
In GPT-2, the unembedding matrix is not a separate learned parameter. It is the transpose of the same embedding matrix E used at the input (many newer models untie the two; see the end of this tab):
logitt(token j) = ht · ej (dot product of final rep with token j's embedding)
This means the input embedding matrix E ∈ ℝ|V|×d is used at both ends of the network — once to read tokens into the residual stream, and once to score the final representation against every vocabulary token.
Geometric interpretation
The logit for token j measures how similar the final representation h is to the embedding vector ej (a dot product, so direction and length both count). Tokens whose embeddings point in similar directions to h get high logits; tokens pointing away get low (or negative) logits.
After the forward pass, the model should have moved the representation at the last position toward the embedding direction of likely next tokens. This is the sense in which the model "expects" certain tokens: their embeddings are close to where the representation landed.
Illustrative numbers, not GPT-2 output: the final-position representation h dotted with eight token embeddings. mat gets the highest logit: its embedding has the largest dot product with h.
Parameter efficiency: E has |V| × d ≈ 38M parameters (GPT-2). Tying saves a separate 38M unembedding matrix.
Training signal: Gradients flow through both uses of E simultaneously. The embedding for "cat" is updated both as an input representation and as a target direction in logit space.
Empirical results: Weight tying improves perplexity (Press & Wolf, 2017; Inan et al., 2017). It encodes a strong inductive bias: the residual stream should finish in the same geometric space that tokens occupy.
Not universal
Weight tying is used in GPT-2 and GPT-Neo, but it is not universal. Pythia, Llama 2, Llama 3 and Mistral, among others, use a separate unembedding matrix. The separate matrix adds parameters but gives the model more flexibility to place representations and token embeddings independently.
Autoregressive generation
At inference, the model generates text one token at a time. Each step runs a full forward pass over all tokens seen so far; the output is a probability distribution over the vocabulary at the last position; one token is sampled and appended; repeat.
Temperature
Before softmax, logits can be divided by a temperature parameter τ (written τ here because T is the sequence length). Lower τ sharpens the distribution (the model becomes more deterministic); higher τ flattens it (more uniform, more surprising outputs).
τ → 0 : argmax sampling τ = 1 : standard τ → ∞ : uniform
The KV cache
Without caching, generating token t requires recomputing Q, K, V for all T tokens — O(T²) total work. The KV cache stores the key and value matrices from all previous positions. At step t, the model only computes Q, K, V for the new token, then concatenates the new K and V to the cache. Each generation step is then O(T) in attention.
Sampling strategies
In practice, models rarely use plain temperature sampling over the full vocabulary. Common strategies include top-k sampling (sample from the k highest-probability tokens only), nucleus (top-p) sampling (sample from the smallest set of tokens whose cumulative probability exceeds p), and greedy decoding (always pick the highest-probability token). Each trades off diversity against coherence differently.
Everything is differentiable
Training a language model requires computing the gradient of the loss with respect to every parameter. This is only possible because every operation in the forward pass — all eleven steps — has a well-defined gradient. Backpropagation can then propagate the error signal from the loss all the way back to the embedding matrix.
Gradients for each stage
| Operation | Key gradient | Notes |
|---|---|---|
| Embedding lookup | ∂Loss/∂E[idt] = ∂Loss/∂xt | Gradient flows directly into the embedding row of the token at position t (summed over every position where that token appears) |
| Layer Norm | ∂LN/∂x = γ/σ · (I − 11⊤/d − x̂x̂⊤/d), x̂ = (x−μ)/σ | O(d) per position (cheap); stable gradient magnitude |
| Linear (W) | ∂Loss/∂W = x⊤ · δ | Outer product of input and output gradient (row-vector convention y = xW); same for WQ, WK, WV, WO, Wup, Wdown |
| Softmax (attention) | ∂a/∂s = diag(a) − aa⊤, a = softmax(s) | Jacobian is T×T; causal mask zeroes the upper triangle before this |
| GELU | ∂GELU(x)/∂x = Φ(x) + xφ(x) (GELU(x) = x·Φ(x)) | Smooth approximation to ReLU; non-zero gradient almost everywhere |
| Residual add | ∂(x + f(x))/∂x = I + ∂f/∂x | The identity term means gradient always passes through; no vanishing |
| Unembedding (E⊤) | ∂Loss/∂h = ∂Loss/∂logits · E | With weight tying (GPT-2), this gradient also updates E, the input embedding |
| Softmax → cross-entropy | ∂lt/∂logitst = Pt − yt | Elegantly simple: predicted probs minus one-hot true label (per-token loss lt) |
From forward pass to training
The forward pass computes a probability distribution over vocabulary at each position. The cross-entropy loss measures how much probability the model assigned to the actual next token:
∂Loss/∂logitst = (Pt − yt) / T where yt is a one-hot for the true token
Notation: Loss is the training loss; L stays the number of blocks, as in Lesson 2. Positions are numbered from 0.
Backpropagation propagates this gradient through all eleven forward-pass stages, accumulating ∂Loss/∂W for every weight matrix. An optimizer (usually AdamW) then updates each parameter in the direction that reduces the loss. This cycle — forward pass → loss → backward pass → update — is what training is.