Attention, Fully Understood
Queries, keys, and values as soft lookup — the mechanism that routes information between tokens.
- → Hand-compute a full attention pass for a tiny example
- → Explain scaling by √d and causal masking
- → Read multi-head attention patterns as information routing
Tokens need to talk
After Module 1.1 you have a sequence of vectors: one per token, each holding the identity of that token and where it sits. Nothing else. The vector for cat is byte-for-byte the same in the cat sat on the mat and in the cat 5 file was corrupted.
That cannot be enough. To predict what follows …the store, John gave a drink to, the vector sitting at to has to somehow know that a name appeared earlier and which one it was. Information has to move between positions.
The mechanism is a soft dictionary lookup. In an ordinary hash map you hold a key, compare it against the stored keys, find the one that matches, and take that entry's value. Attention does the same thing with one change: instead of matching exactly one key, it scores every key for similarity and returns a weighted blend of all the values.
Three roles, three names, and each is just a linear projection of the residual-stream vector at that position:
The queries and keys live in a space of size , typically much smaller than the residual stream's — 64 vs 768 in GPT-2 small. A head is a narrow window onto a wide stream, and that narrowness is a big part of why heads end up specialised.
The formula, term by term
Here is the whole of attention. Read it as: score every pair, shrink the scores, forbid looking ahead, normalise into a distribution, take the weighted average of the values.
Term by term. is an matrix of scores: entry is , how well token 's advertisement answers token 's question. It is a plain dot product, so it is large when the two vectors point the same way and are long.
is the causal mask: 0 where and where . Adding before the softmax sends those entries to exactly zero probability. Then softmax runs along each row, so every token's weights over its visible predecessors sum to 1. Finally multiplying by takes the weighted average.
Why divide by
Suppose the entries of and are roughly independent with mean 0 and variance 1. Then is a sum of independent terms each with variance 1, so
With the scores would routinely sit around , and gaps of 8 in logit space are enormous: softmax would be nearly one-hot at initialisation, gradients through it would be nearly zero, and training would stall before it started. Dividing by puts the scores back at scale , where softmax is soft and its gradient is healthy.
Why the mask
A language model must predict token from tokens . Without the mask, position 3 could read position 7 and the training objective would be trivially cheatable. But there is a second, practical reason the mask is triangular rather than a loop over prefixes: one forward pass over a length- sequence produces training examples at once, because each row of the masked matrix already sees exactly the right prefix. That is a large part of why transformers train so much faster than RNNs.
A full pass by hand: 3 tokens, d = 4
Small enough to check every number with a pen. Sequence: the cat sat, residual stream width , one head with . The three input vectors, stacked as rows of :
The head's three projection matrices, each :
Step 1 — project. Multiply each row of by each matrix. For sat, . All nine vectors:
Step 2 — score. , so . For instance :
Step 3 — scale and mask. Divide by and set the upper triangle to :
Step 4 — softmax each row. Row 3, worked out: subtract the row max 3.54 to get , exponentiate to , divide by the sum 1.736:
Step 5 — mix the values. . Row 3: .
Row 1 is exactly : the first token can only attend to itself, so a head can never do anything useful at position 1. In real models this shows up as attention sinks — heads dump unwanted probability mass onto the first token when they have nothing to say. In production a BOS token is usually prepended precisely to give them somewhere harmless to point.
Many heads, one stream
One head can express one routing rule at a time — the softmax forces its weights to compete for a single unit of probability mass. Real layers run several heads side by side. GPT-2 small has 12 heads per layer, each with , so the 12 heads together use exactly the same parameter budget as one head of width 768 would.
The textbook presentation concatenates the head outputs and multiplies by one big . Split into per-head blocks and the same equation reads much more usefully:
A sum, not a tangle. Each head reads the residual stream through its own narrow projection, does its own routing, and adds its own contribution back. Heads in the same layer never see each other. That is what makes them tractable to study one at a time — and why the field says “head 5.1” the way a biologist says “this neuron.”
Some head types recur across models trained by different labs on different data — previous-token heads, duplicate-token heads, induction heads (which complete , the star of Module 3.2), and name-mover heads (Module 3.5). This partial universality is one of the field's most encouraging findings: it suggests there is a shared set of algorithms to discover, not one private mess per model.
Play: patterns and the geometry behind them
Two toys, top-down. The first shows you what attention patterns look like: four hand-designed heads, each imitating a head type that really occurs in trained models, over three sentences. The second shows you where a pattern comes from: drag vectors around a plane and watch geometry turn into probabilities.
Fires on the token immediately to the left. Real models grow these in layer 0–1; they are the feed for induction heads in Module 3.2.
These heads are hand-written scoring rules, not weights lifted from a model — the point is to make the shape of a pattern legible before you go stare at real ones (the problem set sends you to do exactly that).
The head returns 0.74·v(store) + 0.25·v(Mary) + 0.01·v(went) + 0.00·v(the). That mixture is what gets written back into the residual stream.
Things to try: (1) On the Mary/John sentence, select the duplicate-token head and click the second John — that single arrow is the raw signal the IOI circuit uses to work out which name is not the answer. (2) Click a token near the start of any sentence and turn the causal mask off: watch mass flood into the future and the entropy jump. That is the model cheating, and it is why the mask exists. (3) In the QK playground, set the divisor to and watch the pattern collapse to nearly uniform — then crank query length up to 8× and watch it sharpen back. That is precisely the trade the is managing: score magnitude grows with dimension, so the divisor grows with it too.
Problem set
Do the first one with an actual pen. Attention is the one mechanism in this course worth having in your hands rather than your notes — every circuit result in Part 3 assumes you can do this arithmetic in your sleep.
Sequence a dog barks, , , one causally masked head.
Compute , , , the score matrix, the masked scaled scores, the attention matrix, and the output. Then answer: which token does barks attend to most, and would that change if you dropped the ?
Let and be independent random vectors in whose entries are iid with mean 0 and variance 1. Compute and . Then explain, in terms of the softmax gradient, why a typical score of is a training problem and a typical score of is not.
Before touching a model: a head has learned to attend to the token immediately to its left. Sketch its attention matrix for a 6-token sequence — mark which cells are near 1 and which near 0.
Then answer three things. (a) What must be reading, given that the residual stream at this point contains token identity and position? (b) What does row 1 look like, and why? (c) Could this head exist in layer 0 of a model with no positional information at all?
Prove that with causal masking, the attention output at position is completely unchanged if you replace every token after position with anything you like. Then use that fact to explain why one forward pass over a length- sequence gives independent training signals instead of one — and say what would break if the mask were .
Implement attention(X, Wq, Wk, Wv, causal=True) for one head, then mha(X, Wq, Wk, Wv, Wo, n_heads) where the weights are the full matrices and you reshape into heads. No loops over positions — use matrix multiplies and np.triu for the mask.
Success checks, all three: (1) your single-head function reproduces the by-hand answer above to 3 decimals; (2) every row of the attention matrix sums to 1 and the upper triangle is exactly 0; (3) running mha with n_heads=1 and Wo = I gives the same answer as your single-head function.
Then a diagnostic: feed random with and print the standard deviation of the pre-softmax scores with and without the . Confirm the ratio is .
Open a real attention viewer — BertViz (linked below, runs in Colab in about ten lines against GPT-2) or the attention view in Neuronpedia. Feed it the sentence When Mary and John went to the store, John gave a drink to.
Find and screenshot: (1) a head whose pattern is a clean line one below the diagonal; (2) a head that puts most of its mass on the first token regardless of query; (3) a head at the final position that attends to one of the two names more than the other. For each, write one sentence on what it might be for — and one sentence on what evidence would be needed to actually believe that.
Check yourself
Go deeper
Read the visual explainers first, then the paper. Vaswani et al. is short and famous and mostly about machine translation plumbing you do not need — the reading note below tells you which two pages matter.