Chapter 4 · Section 4.5 · 55 min

Multi-head attention

Take the sentence "the cat quietly sat". When the model processes "sat", it would like to know two different things at once. Who is sitting (the subject, "cat")? And what came just before it ("quietly")? One attention head produces one set of weights per query, so it can put its weight on the subject, or on the previous token, or split it between them. It cannot do both cleanly. And if it splits, something worse happens than a loss of sharpness, which we will see in a moment.

The fix in Vaswani et al. (2017) is to run several attention heads side by side, each with its own queries, keys, and values, each free to attend somewhere different, and to combine their outputs at the end. This section explains why that helps, implements it the way every production codebase does (with one reshape and one transpose instead of a loop), counts its parameters and costs exactly, and surveys what trained heads are known to do.

One head blends what it finds

Suppose the values carry token identity as one-hot vectors, and a single head at "sat" splits its weight evenly between the subject "cat" and the previous token "quietly". Its output is

o=0.5 ecat+0.5 equietly.\mathbf{o} = 0.5\,\mathbf{e}_{\text{cat}} + 0.5\,\mathbf{e}_{\text{quietly}} .

Which of the two is the subject? The output cannot say. A weighted average is symmetric in its inputs, so once two sources are blended into the same coordinates, the information about which source was found by which question is gone. You would get the same vector if "quietly" were the subject and "cat" the previous token.

Two heads fix this. Head 1 attends to the subject and returns ecat\mathbf{e}_{\text{cat}}. Head 2 attends to the previous token and returns equietly\mathbf{e}_{\text{quietly}}. Their outputs are kept in separate coordinates (concatenated), so the next layer can read "subject is cat" and "previous token is quietly" independently. Each head is a separate question with a separate answer.

Python · cell 1

There is also a capacity argument. From §4.2, a head's similarity is the bilinear form WQWK⊤\mathbf{W}_Q\mathbf{W}_K^\top, of rank at most dkd_k. One head with dk=dd_k = d has a single full-rank similarity but a single softmax. Splitting the same width into hh heads of dk=d/hd_k = d/h gives hh separate similarities, each of rank d/hd/h, and hh separate softmaxes. Neither is strictly more expressive than the other. The bet behind multi-head attention, borne out in practice, is that many cheap, independent lookups are worth more than one rich one. Vaswani et al. found single-head attention 0.9 BLEU worse than their best setting on translation, and quality dropped again with too many heads, so the number of heads is a real trade-off and not "more is better".

The definition

Each head i∈{1,…,h}i \in \{1, \dots, h\} has its own projections WQ(i),WK(i)∈Rd×dk\mathbf{W}_Q^{(i)}, \mathbf{W}_K^{(i)} \in \R^{d\times d_k} and WV(i)∈Rd×dv\mathbf{W}_V^{(i)} \in \R^{d\times d_v}, and computes ordinary scaled dot-product attention (§4.3),

H(i)=softmax⁡ ⁣((XWQ(i))(XWK(i))⊤dk+M)XWV(i)  ∈  RT×dv,\mathbf{H}^{(i)} = \operatorname{softmax}\!\left(\frac{(\mathbf{X}\mathbf{W}_Q^{(i)})(\mathbf{X}\mathbf{W}_K^{(i)})^\top}{\sqrt{d_k}} + \mathbf{M}\right)\mathbf{X}\mathbf{W}_V^{(i)} \;\in\; \R^{T\times d_v},

with M\mathbf{M} the mask of §4.4. The head outputs are concatenated along the feature axis and mixed by an output projection WO∈Rhdv×d\mathbf{W}_O \in \R^{hd_v\times d},

MultiHead⁡(X)=[H(1) ∣ H(2) ∣ ⋯ ∣ H(h)] WO  ∈  RT×d.\operatorname{MultiHead}(\mathbf{X}) = \big[\mathbf{H}^{(1)} \,\big|\, \mathbf{H}^{(2)} \,\big|\, \cdots \,\big|\, \mathbf{H}^{(h)}\big]\,\mathbf{W}_O \;\in\; \R^{T\times d}.

In plain words, run hh small attention heads in parallel, put their answers side by side, and use one linear map to turn the combined answer back into a width-dd vector per token.

The standard choice is dk=dv=d/hd_k = d_v = d/h. Then the concatenation has width exactly dd, and, as we will count below, the whole layer costs the same as one head of width dd. GPT-2 small uses d=768d = 768 and h=12h = 12, so dk=64d_k = 64. Llama 3 8B uses d=4096d = 4096 and h=32h = 32, so dk=128d_k = 128. Head widths of 64 or 128 are by far the most common (Gemma is a notable exception at 256), and models get wider mostly by adding heads.

The output projection, and why heads add up

Split WO\mathbf{W}_O into hh horizontal blocks of dvd_v rows each, WO(1),…,WO(h)∈Rdv×d\mathbf{W}_O^{(1)}, \dots, \mathbf{W}_O^{(h)} \in \R^{d_v\times d}. Block matrix multiplication gives

[H(1)∣⋯∣H(h)](WO(1)⋮WO(h))=∑i=1hH(i)WO(i).\big[\mathbf{H}^{(1)} \mid \cdots \mid \mathbf{H}^{(h)}\big] \begin{pmatrix} \mathbf{W}_O^{(1)} \\ \vdots \\ \mathbf{W}_O^{(h)} \end{pmatrix} = \sum_{i=1}^{h} \mathbf{H}^{(i)}\mathbf{W}_O^{(i)} .

In plain words, "concatenate, then project" is the same as "project each head separately, then add".

This identity is worth having in your pocket. It says the heads are independent and additive. Each head reads from the input, computes its own pattern, and writes its own contribution, and the contributions add. Elhage et al. (2021) build their whole analysis of Transformers on this view, in which each head writes into a shared residual stream (§5.1), with the head's OV circuit WV(i)WO(i)\mathbf{W}_V^{(i)}\mathbf{W}_O^{(i)} deciding what it writes. It also tells you what WO\mathbf{W}_O is for. Without it, each head's output would be stuck in its own fixed slice of coordinates. With it, every head can write in any direction of the width-dd space.

Reshape, transpose, and no loops

The definition suggests a loop over heads, and the first version most people write has one. Production code has none. The trick is to compute all heads' projections with one matrix product and then reshape.

Stack the per-head projections side by side, WQ=[WQ(1)∣⋯∣WQ(h)]∈Rd×hdk\mathbf{W}_Q = [\mathbf{W}_Q^{(1)} \mid \cdots \mid \mathbf{W}_Q^{(h)}] \in \R^{d\times hd_k}, and the same for keys and values. Then Q=XWQ\mathbf{Q} = \mathbf{X}\mathbf{W}_Q of shape (B,T,hdk)(B, T, h d_k) holds every head's queries, with head ii in columns idki d_k to (i+1)dk−1(i+1)d_k - 1. Two moves put the heads on their own axis.

  1. Reshape the last axis into two, (B,T,hdk)→(B,T,h,dk)(B, T, hd_k) \to (B, T, h, d_k). In row-major memory this splits each token's vector into hh consecutive chunks of dkd_k, which is exactly head ii's columns. No data moves.
  2. Transpose the head and time axes, (B,T,h,dk)→(B,h,T,dk)(B, T, h, d_k) \to (B, h, T, d_k). Now each (batch, head) pair owns a (T,dk)(T, d_k) matrix, and the batched matrix product treats (B,h)(B, h) as batch dimensions.

Attention then runs on all heads at once. Scores are (B,h,T,T)(B, h, T, T) and outputs (B,h,T,dv)(B, h, T, d_v). To merge, undo both moves. Transpose back to (B,T,h,dv)(B, T, h, d_v) and reshape to (B,T,hdv)(B, T, hd_v), which is the concatenation, then multiply by WO\mathbf{W}_O. (See §0.1 for why reshape is free and transpose only changes strides.)

The order of those two moves is the single most common bug in multi-head attention, and you met it in §0.1, where Exercise 0.1c had you write split_heads and merge_heads. Reshaping (B,T,d)(B, T, d) directly to (B,h,T,dk)(B, h, T, d_k) gives the right shape and the wrong contents, since what it calls head 1 holds whole tokens from the second half of the sequence instead of the second slice of every token. Attention computed on that runs without complaint, training proceeds, and the model is worse. The widget below shows the two splits in color, for any dd and hh.

How does one (T, d) matrix become h heads, and what does the classic reshape bug do?
Each row is one token's query vector, colored by token. The correct split reshapes to (T, h, d_k) and then transposes. The buggy one reshapes straight to (h, T, d_k).
Loading interactive figure…

Here is the full layer, vectorized, checked against a loop over heads and against the "project each head, then add" identity.

Python · cell 2
Interview

Multi-head causal self-attention with no Python loops

This is the interview problem, in the form labs ask it. Implement multi_head_attention(X, W_Q, W_K, W_V, W_O, h, causal=True) for X of shape (B, T, d), square weight matrices of shape (d, d) holding all heads side by side (dk=d/hd_k = d/h), and return Y of shape (B, T, d). Use scaled dot-product attention with the head width dkd_k in the scale, and a causal mask when causal is true. There must be no Python loop (or comprehension) over heads, positions, or batch elements. The tests count the lines your function executes with 64 heads, so a loop will be caught.

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

What it costs, counted exactly

Parameters. With dk=dv=d/hd_k = d_v = d/h, the stacked WQ\mathbf{W}_Q, WK\mathbf{W}_K, WV\mathbf{W}_V are each d×dd\times d, and WO\mathbf{W}_O is d×dd\times d. So

params=4d2(plus 4d if every projection has a bias),\text{params} = 4d^2 \quad(\text{plus } 4d \text{ if every projection has a bias}),

independent of the number of heads. Splitting into heads is free in parameters. For GPT-2 small, which has biases, that is 4×7682+4×768=2,362,3684 \times 768^2 + 4 \times 768 = 2{,}362{,}368 per layer, or about 28.3M across its 12 layers, close to a quarter of its 124M parameters. (GPT-2's code stores the first three as one c_attn layer of shape 768×2304768 \times 2304 and the last as c_proj. The totals agree.)

Nothing forces hdk=dhd_k = d, though. Gemma 7B has d=3072d = 3072 and 16 heads of width dk=256d_k = 256, so its stacked queries are 4,0964{,}096 wide, wider than the model, and WO∈R4096×3072\mathbf{W}_O \in \R^{4096\times 3072} maps the concatenated heads back down. In general the four matrices hold 4 d hdk4\,d\,hd_k weights. Exercise 4.5e counts both cases.

Modern models also often share keys and values across groups of query heads, grouped-query attention. With hh query heads and nkvn_{kv} key-value heads, each shared by a group of h/nkvh/n_{kv} query heads, WK\mathbf{W}_K and WV\mathbf{W}_V shrink to d×nkvdkd\times n_{kv} d_k, and nkv=hn_{kv} = h is the ordinary layer. Its purpose is to shrink what must be stored at inference time, so it is taught with that cache, in §6.5 and §12.5.

Compute. For one sequence of length TT, counting a multiply-add as 2 FLOPs, the projections cost 4×2Td2=8Td24 \times 2Td^2 = 8Td^2, the scores cost h×2T2dk=2T2dh \times 2T^2d_k = 2T^2d, and the weighted sum of values another 2T2d2T^2d. The number of heads cancels again. §4.7 turns these into real numbers.

Memory. Here the heads do not cancel. A naive implementation materializes one T×TT\times T score matrix per head, so hT2h T^2 numbers per sequence and per layer. More heads of the same total width mean more score matrices, which is one reason head widths stay at 64 or 128 instead of shrinking.

Python · cell 3

GPT-3's attention layers hold about 58 billion of its 175 billion parameters, a third, which is the same fraction as in every standard block (4d24d^2 of 12d212d^2, as §5.6 counts).

Core

Count attention parameters

Implement attention_param_count(d, h, d_k=None, bias=False) returning the number of parameters in one multi-head attention layer with model width dd, hh heads, and head width dkd_k for queries, keys, and values (default d/hd/h). With bias=True every one of the four projections has a bias vector. Raise ValueError if d_k is not given and h does not divide d.

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

What heads learn

Here we leave theorems behind. Everything in this part is an empirical finding about trained models, mostly from studies that look at attention weights or remove heads and measure the damage.

  • Heads specialize. Clark et al. (2019) found heads in BERT that attend to the previous or next token, heads that attend broadly, and heads whose patterns track syntax, for example from a verb to its direct object or from a noun to its determiner, with accuracy well above simple baselines. Many heads put most of their weight on the separator token, which looks like the "attend to nothing" behavior of §4.4.
  • A few heads do most of the work. Voita et al. (2019) classified the heads of a translation model into positional, syntactic, and rare-word heads, and found that pruning 38 of the 48 encoder heads cost only 0.15 BLEU on English to Russian. Michel et al. (2019) found that many heads can be removed at test time with little loss, and that some layers can be reduced to a single head.
  • Some heads form circuits. In language models, previous-token heads (which you built in Exercise 4.2b) combine with induction heads in a later layer to continue repeated patterns, a mechanism found in models from tiny ones to large ones (Olsson et al. 2022). We build one by hand in §4.7, and circuit analysis traces how heads compose into larger algorithms.

Two cautions keep these findings honest. Redundancy at test time does not mean the heads were useless during training. Extra heads may make optimization easier, which is a reason not to start with fewer. And attention weights are not the same as importance. A head can attend strongly to a token whose value vector is tiny, so it contributes almost nothing (Kobayashi et al. 2020), which is why careful studies measure what removing or patching a head does instead of just staring at its weights.

Core

Mean attention entropy per head

A standard diagnostic during training is the average entropy of each head's attention distribution. Very low entropy means a head has become nearly one-hot, and a sudden collapse of entropy is a warning sign of instability (§5.7). Implement head_entropy(A) for weights A of shape (B, h, T_q, T_k) whose rows sum to 1, possibly with exact zeros from masking. Return an array of shape (h,) with each head's entropy averaged over the batch and the queries, in nats, treating 0log⁡00\log 0 as 0.

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

In PyTorch

A production multi-head attention module is about fifteen lines. This is the shape of nanoGPT's CausalSelfAttention, using the fused kernel from §4.3.

🔥 In PyTorchfor a machine with PyTorch

The .contiguous() before the final .view is not decoration. After the transpose the tensor's memory is no longer laid out row by row, and view refuses to reinterpret non-contiguous memory. (reshape would copy silently instead.) The comprehension over (q, k, v) iterates over three tensors, not over heads, so it costs nothing that grows with hh.

designheadsparams (per layer)score matrices per layernotes
single head, dk=dd_k = d14d24d^21one full-rank similarity, one pattern per token
multi-head, dk=d/hd_k = d/hhh4d24d^2hhthe standard design, same FLOPs
wide heads, hdk>dhd_k > dhh4d hdk4d\,hd_khhGemma 7B, more width per head
grouped-query (GQA), multi-query (nkv=1n_{kv} = 1)hh queries, nkvn_{kv} KV2d2+2dnkvdk2d^2 + 2dn_{kv}d_khha smaller inference cache (§12.5)

Read more

Watch next

🎬 Let's build GPT: from scratch, in code, spelled out. · Andrej Karpathy · starts at 81:59Karpathy turns one head into several running in parallel and concatenates them, then measures the improvement.
🎬 Attention in transformers, step-by-step | Deep Learning Chapter 6 · 3Blue1Brown · starts at 19:19The multiple heads and output matrix segments, including a parameter count for GPT-3.
🎬 Lecture 12.1 Self-attention · DLVUPeter Bloem's lecture, a precise and unhurried derivation of self-attention and multi-head attention from scratch.