Interpretable
Module 1.2 · ~3h

Attention, Fully Understood

Queries, keys, and values as soft lookup — the mechanism that routes information between tokens.

You'll be able to
  • 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
Learn

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.

Key idea
Attention is the only operation in a transformer that moves information between token positions. Embeddings, LayerNorm, and the MLP all act on one position at a time, in parallel, blind to their neighbours. So every question of the form “how did what happened at token 3 reach the prediction at token 40?” is, mechanically, a question about attention.

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.

hard lookupsoft lookup (attention)k1v1k2v2k3v3q =k2out = v2k1v10.62k2v20.28k3v30.10qout = .62 v1 + .28 v2 + .10 v3
Hard lookup returns one value. Soft lookup returns a mixture, weighted by how well each key matched. That is the whole idea — everything after this is bookkeeping about where the queries, keys, and values come from.

Three roles, three names, and each is just a linear projection of the residual-stream vector at that position:

query
qi=WQxiq_i = W_Q\, x_i — what token ii is looking for. “I am a verb; where is my subject?”
key
kj=WKxjk_j = W_K\, x_j — what token jj advertises about itself. “I am a singular noun in subject position.”
value
vj=WVxjv_j = W_V\, x_j — what token jj will hand over if it is attended to. Deliberately separate from the key: what makes you findable and what you contribute are different questions, so they get different matrices.

The queries and keys live in a space of size dheadd_{\text{head}}, typically much smaller than the residual stream's dmodeld_{\text{model}} — 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.

Learn

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.

Attn(Q,K,V)=softmax ⁣(QKdhead+M)V\mathrm{Attn}(Q,K,V) = \mathrm{softmax}\!\left(\frac{QK^\top}{\sqrt{d_{\text{head}}}} + M\right) V

Term by term. QKQK^\top is an n×nn \times n matrix of scores: entry (i,j)(i,j) is qikjq_i \cdot k_j, how well token jj's advertisement answers token ii's question. It is a plain dot product, so it is large when the two vectors point the same way and are long.

MM is the causal mask: 0 where jij \le i and -\infty where j>ij > i. Adding -\infty 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 VV takes the weighted average.

Why divide by dhead\sqrt{d_{\text{head}}}

Suppose the entries of qq and kk are roughly independent with mean 0 and variance 1. Then qk=t=1dqtktq \cdot k = \sum_{t=1}^{d} q_t k_t is a sum of dd independent terms each with variance 1, so

Var(qk)=dtypical qkd\mathrm{Var}(q \cdot k) = d \quad\Longrightarrow\quad \text{typical } |q\cdot k| \approx \sqrt{d}

With dhead=64d_{\text{head}} = 64 the scores would routinely sit around ±8\pm 8, 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 dhead\sqrt{d_{\text{head}}} puts the scores back at scale 1\approx 1, where softmax is soft and its gradient is healthy.

Key idea
The d\sqrt{d} is a temperature. It does not change which key wins — dividing every score by the same positive number preserves the ordering — it changes how sharply the winner beats the rest. It exists so that the mechanism is trainable, not because it is mathematically necessary.

Why the mask

A language model must predict token i+1i+1 from tokens 1..i1..i. 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-nn sequence produces nn 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.

ThecatsatonmatThecatsatonmat−∞−∞−∞−∞−∞−∞−∞−∞−∞−∞keys (what we look at) →queries ↓
The masked score matrix. Row i = what token i can look at. The upper triangle is set to −∞ before the softmax, so it contributes exactly zero probability. Softmax is applied row-wise, so each row sums to 1 over its allowed prefix.
A mask is not a zeroing
Masking has to happen before the softmax, as -\infty added to the scores. If you compute the full softmax and then zero the future entries, the surviving weights no longer sum to 1 and the head silently shrinks its own output. This is a classic implementation bug — and worth remembering because interpretability code that re-runs attention by hand hits it too.
Key idea
The matrix splits cleanly in two. WQW_Q and WKW_K only ever appear together as WQWKW_Q^\top W_K — the QK circuit, which decides where to look. WVW_V and WOW_O only ever appear together as WOWVW_O W_V — the OV circuit, which decides what gets moved. Two independent questions, two independent low-rank maps. Module 3.2 builds the whole theory of circuits on this split.
Learn

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 dmodel=4d_{\text{model}} = 4, one head with dhead=2d_{\text{head}} = 2. The three input vectors, stacked as rows of XX:

X=[101001101101]thecatsatX = \begin{bmatrix} 1 & 0 & 1 & 0 \\ 0 & 1 & 1 & 0 \\ 1 & 1 & 0 & 1 \end{bmatrix} \begin{matrix} \leftarrow \text{the} \\ \leftarrow \text{cat} \\ \leftarrow \text{sat} \end{matrix}

The head's three projection matrices, each 4×24 \times 2:

WQ=[10010110],WK=[10110100],WV=[01101101]W_Q = \begin{bmatrix} 1 & 0 \\ 0 & 1 \\ 0 & 1 \\ 1 & 0 \end{bmatrix},\quad W_K = \begin{bmatrix} 1 & 0 \\ 1 & 1 \\ 0 & 1 \\ 0 & 0 \end{bmatrix},\quad W_V = \begin{bmatrix} 0 & 1 \\ 1 & 0 \\ 1 & 1 \\ 0 & -1 \end{bmatrix}

Step 1 — project. Multiply each row of XX by each matrix. For sat, q3=(1,1,0,1)WQ=(11+10+00+11,  10+11+01+10)=(2,1)q_3 = (1,1,0,1) W_Q = (1{\cdot}1 + 1{\cdot}0 + 0{\cdot}0 + 1{\cdot}1,\; 1{\cdot}0 + 1{\cdot}1 + 0{\cdot}1 + 1{\cdot}0) = (2,1). All nine vectors:

Q=[110221],K=[111221],V=[122110]Q = \begin{bmatrix} 1 & 1 \\ 0 & 2 \\ 2 & 1 \end{bmatrix},\quad K = \begin{bmatrix} 1 & 1 \\ 1 & 2 \\ 2 & 1 \end{bmatrix},\quad V = \begin{bmatrix} 1 & 2 \\ 2 & 1 \\ 1 & 0 \end{bmatrix}

Step 2 — score. S=QKS = QK^\top, so Sij=qikjS_{ij} = q_i \cdot k_j. For instance S32=(2,1)(1,2)=4S_{32} = (2,1)\cdot(1,2) = 4:

S=[233242345]S = \begin{bmatrix} 2 & 3 & 3 \\ 2 & 4 & 2 \\ 3 & 4 & 5 \end{bmatrix}

Step 3 — scale and mask. Divide by dhead=21.414\sqrt{d_{\text{head}}} = \sqrt 2 \approx 1.414 and set the upper triangle to -\infty:

S~=[1.411.412.832.122.833.54]\tilde S = \begin{bmatrix} 1.41 & -\infty & -\infty \\ 1.41 & 2.83 & -\infty \\ 2.12 & 2.83 & 3.54 \end{bmatrix}

Step 4 — softmax each row. Row 3, worked out: subtract the row max 3.54 to get (1.41,0.71,0)(-1.41, -0.71, 0), exponentiate to (0.243,0.493,1)(0.243, 0.493, 1), divide by the sum 1.736:

A=[1.000000.1960.80400.1400.2840.576]A = \begin{bmatrix} 1.000 & 0 & 0 \\ 0.196 & 0.804 & 0 \\ 0.140 & 0.284 & 0.576 \end{bmatrix}

Step 5 — mix the values. out=AV\mathrm{out} = A V. Row 3: 0.140(1,2)+0.284(2,1)+0.576(1,0)=(1.284,0.564)0.140\,(1,2) + 0.284\,(2,1) + 0.576\,(1,0) = (1.284, 0.564).

out=[1.0002.0001.8041.1961.2840.564]\mathrm{out} = \begin{bmatrix} 1.000 & 2.000 \\ 1.804 & 1.196 \\ 1.284 & 0.564 \end{bmatrix}

Row 1 is exactly v1v_1: 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 \langleBOS\rangle token is usually prepended precisely to give them somewhere harmless to point.

What the √d actually bought us
Compare row 3 with and without the scaling. Unscaled, the raw scores (3,4,5)(3,4,5) softmax to (0.090,0.245,0.665)(0.090,\,0.245,\,0.665) — sharper. Scaled by 2\sqrt 2 you get (0.140,0.284,0.576)(0.140,\,0.284,\,0.576). And if this were a real GPT-2 head with dhead=64d_{\text{head}} = 64, dividing by 8 would give (0.293,0.332,0.376)(0.293,\,0.332,\,0.376) — almost flat. Same geometry, three different temperatures. Note also that the dd in d\sqrt d is the head dimension, not dmodeld_{\text{model}}; getting that wrong is a common re-implementation bug.
Learn

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 dhead=64d_{\text{head}} = 64, 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 WOW_O. Split WOW_O into per-head blocks and the same equation reads much more usefully:

attn-outi=h=1HWO(h)jAij(h)WV(h)xj\text{attn-out}_i = \sum_{h=1}^{H} W_O^{(h)} \sum_j A^{(h)}_{ij}\, W_V^{(h)} x_j

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.”

residual stream (d_model = 768) →head 1prev-tokenread+writehead 2duplicateread+writehead 3syntacticread+writehead 4broad avgread+writeone attention layer, H = 4 independent channels
A layer's heads are parallel channels on a shared bus. Each reads the residual stream, routes information between positions, and adds its result back. Nothing is overwritten; the stream only accumulates.
Key idea
Attention is information routing. A head does not “compute” much: it picks a source position and copies a projection of what is there to a destination position. The thinking happens in the MLPs (Module 1.3); attention decides which facts are available to think with.

Some head types recur across models trained by different labs on different data — previous-token heads, duplicate-token heads, induction heads (which complete [A][B][A][B][A][B]\ldots[A] \to [B], 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.

Heads are not clean
Do not over-read the labels. Most heads do several unrelated things depending on context, plenty do nothing legible at all, and a head that looks like a “syntax head” on your ten example sentences may be doing something else entirely on the other 99.99% of the distribution. “Head hh is the X head” is a hypothesis, not an observation.
Safety tie-in
Attention patterns are the most legible surface a transformer has — you can literally draw the arrows. That makes them seductive, and the field has learned to distrust them: an attention weight tells you what was read, not what was used. A head can attend hard at a token and move nothing useful (its OV circuit projects to noise), and a small weight on a high-magnitude value can dominate the output. Whether attention constitutes an “explanation” was contested throughout the 2019 NLP literature and the honest answer is that it is evidence, not proof. Everything in Part 3 — ablation, activation patching, causal scrubbing — exists to close that gap. Keep the reflex: is this correlational or causal?
Explore

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.

Attention patterns: click a token, watch where it looks
Four hand-designed heads over three sentences. The clicked token is the query; arc thickness and box shading are its attention weights over the keys. Turn the causal mask off to see what the model is never allowed to do.
Sentence
Causal mask
Head

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.

The0cat1sat2on3the4mat5because6the7cat8was9tired10.11
Attention weights from “cat
The
0.0%
cat
0.1%
sat
0.1%
on
0.1%
the
0.1%
mat
0.1%
because
0.2%
the
98.4%
cat
0.9%
was
tired
.
Query cat (position 8) puts 98.4% of its mass on the (position 7). Pattern entropy 0.15 bits — 0 bits is a hard pointer, 3.17 bits would be a flat average over everything visible.

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).

QK playground: geometry becomes attention
Drag the orange query and the four keys. The dot product is a projection length — how far a key reaches along the query's direction — and softmax turns those lengths into a mixture. Nothing here is learned; you are the weights.
Divide scores by
k1k2k3k4q
q·k → score → weight
k1store4.31 ÷ 1.41 = 3.05
74.0%
k2Mary2.77 ÷ 1.41 = 1.96
24.9%
k3went-2.35 ÷ 1.41 = -1.66
0.7%
k4the-2.97 ÷ 1.41 = -2.10
0.4%

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.

Softmax picks store with 74.0% of the mass; pattern entropy 0.90 bits (2.00 = perfectly flat over four keys). Largest raw dot product 4.31, largest score after dividing 3.05.

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 64=8\sqrt{64} = 8 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 d\sqrt d is managing: score magnitude grows with dimension, so the divisor grows with it too.

Practice

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.

1.A full attention pass, by handpencil & paper

Sequence a dog barks, dmodel=4d_{\text{model}} = 4, dhead=2d_{\text{head}} = 2, one causally masked head.

X=[110001101011],  WQ=[01101101],  WK=[11011010],  WV=[20011102]X = \begin{bmatrix} 1 & 1 & 0 & 0 \\ 0 & 1 & 1 & 0 \\ 1 & 0 & 1 & 1 \end{bmatrix},\; W_Q = \begin{bmatrix} 0 & 1 \\ 1 & 0 \\ 1 & 1 \\ 0 & 1 \end{bmatrix},\; W_K = \begin{bmatrix} 1 & 1 \\ 0 & 1 \\ 1 & 0 \\ 1 & 0 \end{bmatrix},\; W_V = \begin{bmatrix} 2 & 0 \\ 0 & 1 \\ 1 & -1 \\ 0 & 2 \end{bmatrix}

Compute QQ, KK, VV, 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 2\sqrt 2?

2.Derive the √dpencil & paper

Let qq and kk be independent random vectors in Rd\mathbb{R}^d whose entries are iid with mean 0 and variance 1. Compute E[qk]\mathbb{E}[q \cdot k] and Var(qk)\mathrm{Var}(q \cdot k). Then explain, in terms of the softmax gradient, why a typical score of ±8\pm 8 is a training problem and a typical score of ±1\pm 1 is not.

3.Predict the previous-token headpencil & paper

Before touching a model: a head has learned to attend to the token immediately to its left. Sketch its n×nn \times n attention matrix for a 6-token sequence — mark which cells are near 1 and which near 0.

Then answer three things. (a) What must WQWKW_Q^\top W_K 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?

4.What the mask guaranteespencil & paper

Prove that with causal masking, the attention output at position ii is completely unchanged if you replace every token after position ii with anything you like. Then use that fact to explain why one forward pass over a length-nn sequence gives nn independent training signals instead of one — and say what would break if the mask were ji+1j \le i+1.

5.Single-head, then multi-head, in NumPycode

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 dmodel×dmodeld_{\text{model}} \times d_{\text{model}} 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 XX with dhead=64d_{\text{head}} = 64 and print the standard deviation of the pre-softmax scores with and without the d\sqrt d. Confirm the ratio is 88.

6.Go look at real attention patternsexplore

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.

0 of 6 problems marked done
Check

Check yourself

1.
Which operation in a transformer block moves information between token positions?
2.
Why are attention scores divided by dhead\sqrt{d_{\text{head}}}?
3.
A causal mask is applied by adding -\infty to the future entries before the softmax. What goes wrong if you instead compute a full softmax and then zero the future entries?
4.
A head's attention weight from position 20 to position 4 is 0.9. What have you learned?
5.
GPT-2 small uses 12 heads of width 64 per layer rather than 1 head of width 768. What does this buy?
6.
Why do WKW_K and WVW_V exist as separate matrices instead of just using one projection for both roles?
7.
In the hand-worked example, row 1 of the attention matrix was (1,0,0)(1, 0, 0). What does that tell you about the first position?
Answer all 7 questions to submit.
Submit your answers to complete this check.
Go deeper

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.

EssentialThe Illustrated Transformerblog
Jay Alammar · 2018 · 45 min
Read this before the paper. It draws every tensor shape in the attention computation, which is exactly the thing that is hard to hold in your head from equations. Stop when it reaches the decoder cross-attention section — modern decoder-only LLMs do not have it.
EssentialAttention in transformers, step-by-step (Deep Learning, Chapter 6)video
3Blue1Brown (Grant Sanderson) · 2024 · 26 min
The best available animation of Q/K/V as a geometric operation. Watch specifically for the moment the query and key spaces are shown as a low-dimensional bottleneck — that picture is what makes the QK-circuit framing in Module 3.2 feel obvious later.
EssentialAttention Is All You Needpaper
Vaswani, Shazeer, Parmar, Uszkoreit, Jones, Gomez, Kaiser & Polosukhin · 2017 · 1h
How to read it: §3.2 (scaled dot-product and multi-head attention) is the whole reason you are here — read it twice, including footnote 4, which is the √d variance argument you derived in the problem set. Skim §3.3–3.5. Skip §4, §5 and all of the machine-translation results; the encoder-decoder architecture in Figure 1 is not what modern LLMs use. Read §7 for a period-piece view of what the authors thought they had built.
A Mathematical Framework for Transformer Circuitspaper
Elhage, Nanda, Olsson et al. (Anthropic) · 2021 · 1h (first pass)
First pass only: read "Attention Heads are Independent and Additive" and "Attention Heads as Information Movement", and let the tensor-product notation wash over you. The one idea to take away now is the QK/OV split. You will read the whole thing properly in Module 3.2.
Let's build GPT: from scratch, in code, spelled outvideo
Andrej Karpathy · 2023 · 2h (do-along)
The spine of Part 1 — start it now and finish it during Module 1.3. For this module, the segment where he builds up from a simple average, to a masked average with a lower-triangular matrix, to full self-attention is the single clearest derivation of the causal mask anywhere. Type it yourself; do not watch it.
BertViz: attention visualization for NLP modelstool
Jesse Vig · 2019 · 20 min setup
The tool for the explore problem above. The README's Colab links get you real GPT-2 attention patterns in about ten lines. Use the "model view" first to scan all 144 heads at once, then "head view" to inspect the interesting ones.