The Output Projection: How 64 Attention Heads Become One Thought

The Output Projection: How 64 Attention Heads Become One Thought

Sixty-four attention heads have just finished work. Each produced 128 numbers, and not one of them knows what the other sixty-three found. The output projection, the matrix written W_O, is the operation that fixes that. It is also the least explained matrix in the block, usually waved through as “concatenate the heads and project”.

This article does two things. First it works a complete output projection by hand, on a toy small enough to check with a pen: 3 heads of 2 numbers each, and a 6 x 6 grid of weights. Every number below is checkable. Second it follows the result out of the block and into the residual stream, and shows why one addition sign fixes the width of the model at 8,192 for all 80 layers.

The running model is the one used throughout the series and in the previous part on why 64 heads beat one: 80 layers, d_model 8,192, 64 query heads, 8 key/value heads, head_dim 128.

Inside the Inference Stack · Part 5 of 11
  1. Part 1. How an LLM Answers a Question: The Complete Inference Path
  2. Part 2. Byte-Pair Encoding Explained: How LLMs Turn Text Into Tokens
  3. Part 3. Inside One Transformer Block: The Residual Stream and Its Seven Matrices
  4. Part 4. Multi-Head Attention Explained: Why 64 Heads Instead of One
  5. Part 5. The Output Projection: How 64 Attention Heads Become One Thought (you are here)
  6. Part 6. The Feed-Forward Network: Where a Transformer Keeps What It Knowscoming 14 Aug
  7. Part 7. Mixture of Experts Explained: Conditional Computation From Zerocoming 15 Aug
  8. Part 8. Attention Is All You Need, Dissected: The 2017 Figure, Box by Boxcoming 16 Aug
  9. Part 9. The Roofline Model: Why LLM Decode Is Memory-Boundcoming 17 Aug
  10. Part 10. Continuous Batching and PagedAttention: How vLLM Keeps a GPU Busycoming 18 Aug
  11. Part 11. Benchmark Your Own LLM Serving Stack: Two Measurements, One Afternooncoming 19 Aug

Where we are: 64 sealed boxes

Definition

Output projection (W_O)

The 8,192 x 8,192 matrix that multiplies the concatenated head outputs and produces the single vector the attention branch contributes to the residual stream.

Origin: it arrived with multi-head attention in the 2017 transformer paper, written W^O there. It exists because splitting attention into heads leaves you with 64 separate results and the block is contractually required to return one vector of exactly d_model numbers. Something has to put the pieces back together, and that something also turned out to be where most of the useful work happens.

Why it matters: it is the only path by which any two heads can ever influence each other. Remove it and multi-head attention degenerates into 64 unrelated operations sharing a container.

Attention has run and each of the 64 heads produced 128 numbers. Lay them side by side and you have 8,192 numbers again, one vector, the same width as the thing that went in.

It is not one vector in any useful sense. Numbers 0 to 127 came from head 1, numbers 128 to 255 came from head 2, and they are neighbours in memory that have never influenced each other, not once. Adjacency is not communication, which is a distinction worth internalising well beyond transformers if you spend time reading memory layouts for a living.

the 64 head outputs, placed next to each other … 59 more boxes … head 1head 2head 3 head 4head 64 0–127128–255256–383 384–511 nothing has crossed between boxes. not once. the walls are solid. it looks like one vector of 8,192, but it behaves like 64 unrelated lists

Sixty-four head outputs laid end to end. It has the shape of one 8,192-number vector and the behaviour of 64 unrelated lists.

Here is why that matters. Say head 1 found “this is a definition question” and head 23 found “the important noun is equation”. Both findings are real, both are correct, and neither is worth much alone. The thought the model actually needs is “define the word equation”, and that thought is a combination of the two. Right now it cannot form, because the two findings sit in different compartments and nothing connects the compartments.

head 1 found: “this is a definition question” head 23 found: “the key noun is equation” no route “define the word equation” the thought the model needs — and cannot currently form

Two correct findings in two sealed boxes. The conclusion the model needs sits between them and has no way to assemble itself.

Section takeaways

  • Concatenated head outputs look like one 8,192-number vector and behave like 64 unrelated lists of 128.
  • Head boundaries are memory adjacency and nothing more. No information has crossed them at this point.
  • Two correct findings in two heads cannot combine into the conclusion the model needs without a mixing step.
  • W_O exists because the block must return exactly d_model numbers, and it is the only route between heads.

The multiply, worked by hand

The toy: 3 heads, 2 numbers each

Three heads have just finished. Head 1 returned 3, 1. Head 2 returned 0, 2. Head 3 returned 5, 4. Concatenated, that is the 6-number vector [3, 1, 0, 2, 5, 4], in three sealed groups of two. The real model is 64 heads of 128 numbers, giving 8,192. Same structure, bigger numbers, and no additional ideas.

three head outputs 3 1 0 2 5 4 head 1head 2head 3 laid end to end — the concatenated vector [ 3 1 | 0 2 | 5 4 ] 6 numbers, 3 sealed groups

Three head outputs concatenated into six numbers. The group boundaries exist in your head and in the diagram, and nowhere in the arithmetic that follows.

W_O is a grid of weights, one column per output

Six numbers in, six numbers out, so W_O here is a 6 x 6 grid. Read it by column, because each column is the complete recipe for one output number: how much of each of the six inputs to use. Column 1 is the recipe for output 1, column 2 is a different recipe for output 2, and so on for six independent recipes over the same six inputs. In the running model there are 8,192 columns over 8,192 inputs, which is 67 million learned weights per layer.

Input out1 out2 out3 out4 out5 out6
in1 (head 1) 0.5 0.1 0.0 0.3 0.0 0.2
in2 (head 1) 0.0 0.4 0.2 0.0 0.1 0.0
in3 (head 2) 0.2 0.0 0.5 0.1 0.0 0.3
in4 (head 2) 0.0 0.3 0.0 0.4 0.2 0.0
in5 (head 3) 0.8 0.0 0.1 0.0 0.6 0.1
in6 (head 3) 0.1 0.2 0.0 0.5 0.0 0.4

Analogy

Each column is a recipe and the six inputs are the ingredients on the bench. Output 1 takes a lot of ingredient 5, a little of 1 and 6, and none of the rest. Output 3 is a completely different dish made from the same bench.

Where it breaks: a cook chooses proportions on purpose and can taste the result. These 67 million proportions were fitted by gradient descent to reduce a loss, so most of them correspond to nothing a person would recognise as an ingredient.

out1out2out3 out4out5out6 in1 (h1)in2 (h1) in3 (h2)in4 (h2) in5 (h3)in6 (h3) 0.50.10.00.30.00.2 0.00.40.20.00.10.0 0.20.00.50.10.00.3 0.00.30.00.40.20.0 0.80.00.10.00.60.1 0.10.20.00.50.00.4 one column = one recipe real W_O is 8,192 × 8,192 — 67 million weights, all learned

The same grid. A column is a recipe for one output number, and the row labels are the only place the head boundaries appear.

Output number 1, every step

Take the input vector and column 1. Multiply matching positions, then add the six results. The six products are 3(0.5) = 1.5, then 1(0.0) = 0.0, then 0(0.2) = 0.0, then 2(0.0) = 0.0, then 5(0.8) = 4.0, then 4(0.1) = 0.4. Add them: 1.5 + 0.0 + 0.0 + 0.0 + 4.0 + 0.4 = 5.9.

Now group those products by which head they came from. Head 1 contributed 1.5, head 2 contributed 0.0, head 3 contributed 4.4. One output number, built from two heads at once.

input 3 1 0 2 5 4 column 1 0.5 0.0 0.2 0.0 0.8 0.1 multiply 1.5 0.0 0.0 0.0 4.0 0.4 from h1from h2from h3 add 1.5 + 0.0 + 0.0 + 0.0 + 4.0 + 0.4 = 5.9 5.9 output number 1 contributions came from head 1 (1.5) and head 3 (4.4). head 2 contributed nothing.

Output 1 in full. Two of the six products come from head 1, two from head 2, two from head 3, and the final addition treats all six identically.

The other five outputs

Repeat with each remaining column. Same six inputs every time, different recipe every time, so no two outputs are built the same way.

Output From head 1 From head 2 From head 3 Total
out1 1.5 0.0 4.4 5.9
out2 0.7 0.6 0.8 2.1
out3 0.2 0.0 0.5 0.7
out4 0.9 0.8 2.0 3.7
out5 0.1 0.4 3.0 3.5
out6 0.6 0.0 2.1 2.7

Head 3 dominates output 1 and is nearly absent from output 3. Head 2 is silent in outputs 1, 3 and 6. All three heads land in outputs 2 and 4. Nothing in the input said any of that, and it is entirely the grid’s doing.

Section takeaways

  • The output projection is one matrix multiply and contains no separate merge step.
  • Every column is an independent recipe for one output number over every input number.
  • In the worked toy, output 1 is 5.9, assembled from 1.5 of head 1 and 4.4 of head 3, with head 2 contributing nothing.
  • The real matrix is 8,192 columns over 8,192 inputs, which is 67 million learned weights per layer.
  • Which heads reach which outputs is decided entirely by the grid and not at all by the heads.

The three jobs in one multiply

Job one: combining findings across head boundaries

Look again at where 5.9 came from. Part of it was head 1’s work and part of it was head 3’s, and the plus sign between them did not know or care that a compartment wall sat there. That is the whole of what mixing means. There is no separate merge step, the addition simply runs across the boundaries, and the boundaries mean nothing to it.

Translate that back to the real thing. Head 1 found “this is a question”. Head 3 found “the topic is equations”. Neither is actionable alone, the conjunction is, and after the multiply a single number carries something neither head knew.

head 1 found “this is a question” head 3 found “topic is equations” “define an equation” a thought that exists in neither head — only in the combination

Two findings entering one sum. The output number carries a conclusion that exists in neither head on its own.
eight input numbers 3 1 0 2 5 0 1 1 head 1head 2head 3head 4 one column of weights — learned during training 0.5 0.0 0.2 0.0 0.8 0.0 0.1 0.0 3(0.5) + 1(0) + 0(0.2) + 2(0) + 5(0.8) + 0(0) + 1(0.1) + 1(0) = 1.5 + 4.0 + 0.1 = 5.6 ← ONE output number

A second example: eight inputs, one weight each, one number out. 3(0.5) + 5(0.8) + 1(0.1) = 5.6, and every other term was zeroed by its weight.

The three inputs that survived their weights in that second example came from heads 1, 3 and 4. Three heads, one number, one addition.

3 1 0 2 5 0 1 1 5.6 one number, built from head 1 + head 3 + head 4 do this 8,192 times, with 8,192 different weight columns, and every output can reach every head

The compartment walls drawn on top of the same sum. Do this 8,192 times with 8,192 different columns and every output can reach every head.

Job two: routing, or where a finding lands

Definition

Direction, or subspace, of the residual stream

A particular combination of the 8,192 coordinates that later blocks learn to read for a particular kind of information. Writing “into a subspace” means adding a vector that points along those coordinates.

Origin: the framing was developed in transformer interpretability work published from 2021 onward, which treats the stream as a communication channel that components read from and write to, rather than as an activation to be inspected coordinate by coordinate.

Why it matters: it makes “where a finding lands” a real question with a real answer, and the answer is decided by W_O rather than by the head that produced the finding.

The weights do not only combine. They also decide where the result gets written, because the residual stream is not undifferentiated. Different directions in those 8,192 numbers end up carrying different kinds of information, since later blocks learn to read particular directions for particular things.

head 1 head 2 head 3 W_O the output vector, region by region sentence typetopic grammarleft alone head 3’s finding was routed into the region later blocks read for topic

Head 3’s finding routed into the part of the stream that later blocks read for topic. Which region a finding lands in is decided by the weights, not by which head produced it.

So the division of labour is clean. Heads decide what to look for, and the output projection decides what to do with what they found, including which part of the stream to file it in. A head that studies nouns can have its output written into whichever positions carry noun information, and it never has to know that.

head findings coming in head 1 head 23 head 41 W_O writes each finding into the right region the output vector, by region question typenoun info positionuntouched

The same idea at full width. Some regions of the output get written, some are left untouched, and the choice is per head and per region.

Job three: a zero is a decision too

Go back to the grid and count the zeros. A zero is not an absence of a weight. It is a learned instruction to exclude one input from one output.

Output 1 is the cleanest case. Head 2’s two numbers are 0 and 2. The zero contributes nothing whatever its weight, and the 2 is switched off by a learned 0.0 in column 1. Head 2 is deliberately not heard in output 1, and that decision is made independently for all 8,192 outputs. A head can be loud in some places and silent in others, in the same layer, on the same token.

column 1 again 0.5 0.0 0.2 0.0 0.8 0.1 head 2’s slots — near-zero head 2 is deliberately not heard in output 1 that is a learned decision, made during training, and it is different for all 8,192 outputs so a head can be loud in some places and silent in others

Column 1 with head 2’s two slots highlighted. The zeros are as much a learned choice as the 0.8.

Section takeaways

  • Combining is not a step. It is what happens when a sum runs across boundaries that the arithmetic cannot see.
  • Routing is the second job: the weights decide which direction of the residual stream a finding is written into.
  • A learned zero is an active exclusion, deciding that one head is not heard in one specific output.
  • All three decisions are made independently for each of the 8,192 outputs, on every token.
  • Heads decide what to look for and W_O decides what is done with it, including where it gets filed.

Reading the grid two ways, and why heads specialise

Read a column and you get “which heads feed this output?”. Read a row and you get “where does this head’s information go?”. The row view is the one interpretability researchers use, because a row block shows which directions of the residual stream a given head is able to write into. That is how a claim like “this head writes to the topic subspace” gets established in the first place.

o1o2o3 o4o5o6 h1 ah1 b h2 ah2 b h3 a 0.50.10.00.30.00.2 0.00.40.20.00.10.0 0.20.00.50.10.00.3 0.00.30.00.40.20.0 0.80.00.10.00.60.1 column = the recipe for one output row = where this input gets written

The same numbers, two readings. A column is a recipe for an output; a row is one input’s licence to write.

The row view has a practical consequence. Because W_O multiplies a concatenation, you can slice it into 64 blocks of 128 rows, one block per head, and the block’s output is exactly the sum of the 64 per-head products. Concatenate-then-project and project-per-head-then-add are the same arithmetic. That equivalence is why it is legitimate to talk about “head 12’s contribution to the residual stream” as a thing that exists.

Now take W_O away and see what breaks. Each head’s 128 numbers would go straight onto the residual stream and stay in their own slice forever, so head 12 would occupy positions 1408 to 1535 in every block, in every layer, permanently. Nothing could ever combine two heads.

without W_O rigid lanes — head 12 always in the same slot, forever, unable to reach anywhere else with W_O overlapping regions — any head can write anywhere, and they can share space

Fixed lanes versus overlapping regions. Without the projection a head owns one slot for the life of the model.

The deeper point follows from that. A head is only useful if its finding can be used, and the output projection is the only route by which it can be. During training, a head that discovers something valuable is rewarded only when W_O has learned to carry that output somewhere the rest of the model benefits from. The two co-adapt from the same gradient, so specialisation and routing develop together and neither is worth anything without the other.

heads learn WHAT to look for W_O learns WHAT TO DO with it trained together, from the same gradient a head that finds something useful is only rewarded if W_O carries it somewhere useful so specialisation and routing develop hand in hand — neither works without the other

Heads learn what to look for and the projection learns what to do with it, trained from one gradient signal.

Section takeaways

  • Columns answer “which heads feed this output”. Rows answer “where can this head write”.
  • Slicing W_O into 64 row blocks and summing per-head products is identical arithmetic to one big multiply.
  • That equivalence is what makes “head 12’s contribution to the stream” a well defined quantity rather than a metaphor.
  • Without the projection, every head would own one fixed slice of the stream for the life of the model.
  • Head specialisation and output routing are learned from the same gradient and are useless separately.

The four attention matrices, by size

Put the numbers for the running model side by side, per layer, in bf16, with 64 query heads and 8 key/value heads under grouped-query attention.

Matrix Shape Parameters bf16 size Receives
W_Q 8,192 x 8,192 67.1M 134 MB the normalised residual stream vector
W_K 8,192 x 1,024 8.4M 16.8 MB the normalised residual stream vector
W_V 8,192 x 1,024 8.4M 16.8 MB the normalised residual stream vector
W_O 8,192 x 8,192 67.1M 134 MB the 64 head outputs, concatenated

Two things stand out. The output projection is exactly the same size as W_Q, and it is four times the size of W_K and W_V combined. It accounts for 44 percent of the attention block’s parameters.

W_K and W_V are small for a reason that has nothing to do with importance: grouped-query attention gives them 8 heads instead of 64, to shrink the KV cache. W_O is large for a reason that has everything to do with its job. It holds 8,192 separate recipes, each drawing on all 64 heads, plus the routing decision for every head into every region. That is a lot of decisions to store.

In practice

Across all 80 layers the output projections alone come to 5.4 billion parameters and about 10.7 GB of bf16 weights, which is roughly 8 percent of the whole model. When you are sizing hardware for a model you intend to host yourself, that is one line item bigger than most people’s entire fine-tuned adapter budget.

W_Q 134 MB W_K 17 MB W_V 17 MB W_O 134 MB 44% of the attention block’s parameters are spent on deciding what to do with the results

Relative sizes of the four matrices. Forty-four percent of the attention block is spent deciding what to do with the results, not on producing them.

So the three jobs are combine, select and route, and they are not three steps. They are one multiply, and the same weights do all three at once.

1 · COMBINE findings from different heads land in the same sum 2 · SELECT zero weights exclude a head from an output entirely 3 · ROUTE each finding is written into the region of the stream where it belongs all three happen in one matrix multiply — they are not separate steps

Combine, select, route. Three descriptions of one matrix multiply.

Section takeaways

  • W_O is 67.1M parameters and 134 MB in bf16, identical to W_Q and four times W_K plus W_V.
  • It is 44 percent of the attention block, which is proportionate to the number of decisions it stores.
  • W_K and W_V are small because of grouped-query attention, which is a cache decision and not a statement about importance.
  • Across 80 layers the output projections are 5.4 billion parameters and about 10.7 GB, roughly 8 percent of the model.
  • Combine, select and route are three descriptions of one multiply, not three sequential operations.

Replace or add: the choice that fixes everything

The output projection has produced 8,192 numbers. The block now has to hand something to the next block, and there are exactly two options. Replace means throw away what came in and pass on the new numbers. Add means keep what came in and add the new numbers to it. Transformers add, and almost everything else about the architecture follows from that one choice, as the earlier walk through a single block set up.

option A — replace came in 2 5 1 block made 0 3 9 passed on 0 3 9 the 2 and the 5 are gone forever option B — add came in 2 5 1 + 0 3 9 = 2 8 10 the original is still in there — it was added to, not thrown away

Replace versus add on three numbers. Under addition the original values are still in the total that gets passed on.

Definition

Residual connection

Adding a block’s output to its input instead of replacing it, so the block computes a correction to a running total rather than a new value.

Origin: introduced by He and colleagues in 2015 for image recognition, where networks past about 20 layers were getting worse with depth, and not from overfitting. The skip connection let them train 152 layers. The transformer inherited the idea in 2017 and it is the reason an 80-layer stack is routine.

Why it matters: it is why nothing written early is ever erased, and it is also what forces every layer in the model to be exactly the same width.

What replacing would cost

Follow three blocks under replace. Block 1 notices something important, block 2 produces its own output and hands that on instead, and block 1’s finding is now unrecoverable. Not buried, not hard to reach, gone. Any block that needed block 1’s finding would have to be block 2, because block 2 is the last one that ever sees it. Eighty blocks under replacement would be eighty strangers, each able to cooperate only with its immediate neighbour.

block 1 output finding A block 2 output finding B A overwritten block 3 output finding C B gone too by block 3, findings A and B no longer exist anywhere in the model block 30 could never use something block 3 discovered

Three blocks under replacement. By block 3, findings A and B do not exist anywhere in the model.

What adding buys

The same three blocks under add. Each block’s contribution lands on a running total, nothing is destroyed, so block 30 can still read what block 3 wrote and block 71 can still read both.

start the embedding + block 1 A + block 2 A B + block 3 A B C A, B and C all still present — and all still readable 77 blocks later this is the residual stream: one running total, 160 contributions added to it

The same three blocks under addition. Every contribution is still present in the total, and still readable much later.

Analogy

One page running the whole height of the model. Every block reads the page, writes a note on it, and passes it upward, and nobody has an eraser. It is append-only in the same sense that a log-structured storage engine is append-only, and it buys the same thing: history that later readers can still use.

Where it breaks: a log holds discrete records you can read back one at a time. The page holds a running sum, so two notes written to the same coordinates are added together and can only be separated approximately, by tools like the ones at the end of this article.

Definition

Circuit

A chain in which one block writes a partial result into the stream, a later block reads it and writes a refinement, and a later one again reads that. The chain implements a behaviour that no single component contains.

Origin: the term comes from transformer interpretability work published from 2021, which borrowed it from earlier circuits research on vision models. It was adopted because “which neuron does what” turned out to be the wrong question, and “which path carries what between components” turned out to be answerable.

Why it matters: circuits are the reason multi-step reasoning is possible inside a fixed depth, and they exist only because the stream is additive and nothing gets erased.

the shared page block 3’s note block 12’s note block 40’s note block 71’s note block 3 writes block 30 reads block 3’s note is still perfectly legible 80 blocks, 160 notes, nothing erased researchers call a chain of these notes a “circuit”

Eighty blocks, roughly 160 notes, one page. Block 3’s note is still perfectly legible when block 30 goes looking for it.

Section takeaways

  • A block can replace the stream or add to it, and transformers add.
  • Under replacement, a finding is only usable by the immediately following block and is then gone forever.
  • Under addition every contribution stays in the running total, so block 71 can still read what block 3 wrote.
  • The residual connection came from 2015 image models, where depth past about 20 layers was making networks worse.
  • Circuits, which chain partial results across blocks, exist only because the stream is append-only.

Why the width can never change, and why 80 layers train

You cannot add two lists of different lengths. Every block adds its result to what came in, so every block must produce exactly as many numbers as it received. That is why d_model is 8,192 at every layer boundary in the model. It is not a preference, and addition demands it.

Say plainly what that rules out. You cannot taper a transformer the way you taper a convolutional network, narrowing as it goes deep. You cannot widen the later layers because they are doing harder work. You cannot insert a block that outputs 12,288 numbers between two blocks that expect 8,192. Every architectural change to the stream width has to be made once, globally, for all 80 layers, or it has to be paired with a projection that puts the width back.

The feed-forward network is the clean illustration. It widens to 28,672 and then comes back down to 8,192 before anything is added, so the wide part exists only inside the branch and never touches the page. The next part in this seriescoming 14 Aug works through what happens up there.

works 8,192 + 8,192 fine impossible 8,192 + 28,672 nothing to add the extra 20,480 numbers to this is why the feed-forward widens to 28,672 and then must come back down to 8,192 the wide part exists only inside the branch — it never touches the page

Matching widths add and mismatched widths do not. That single rule fixes the width of the entire model.

One more consequence, easier to feel than to prove. During training a correction signal has to travel from the output all the way back to block 1. Under replacement it passes through 80 transformations and gets scaled at every one, and multiplying 80 small numbers together gives a result indistinguishable from zero, so block 1 learns nothing. Under addition there is a direct path down the running total that the signal travels untouched.

replace — signal weakens at every step block 1block 40block 80 by block 1 the signal has faded to nothing — it cannot learn add — a clean path all the way down signal arrives at full strength block 1block 40block 80 this discovery in 2015 is what made very deep networks possible at all

A signal fading through 80 transformations versus one travelling a clean path. The clean path is what the addition creates.

What the residual stream makes visible

Definition

Logit lens and activation patching

Two ways of reading the stream mid-model. The logit lens applies the final unembedding to the stream partway up and reads off what the model would have predicted at that depth. Activation patching swaps one component’s contribution in from a second run and watches the prediction move.

Origin: the logit lens was introduced in a widely cited 2020 blog post and named for what it does. Activation patching, also called causal tracing, was developed in 2022 work on locating factual associations inside GPT models, adopted because correlational readings of activations could not distinguish a component that causes a prediction from one that merely correlates with it.

Why it matters: both techniques work only because every block adds into the same 8,192-number space, which puts an intermediate stream in the same coordinate system as the final one.

In practice

Treat the output of a logit lens or a patching experiment as evidence and not as an explanation. Both have known failure modes, particularly on models whose intermediate representations are not well aligned with the final unembedding, so a clean-looking readout can be an artefact of the tool rather than a fact about the model.

h1 h2 h3 … 61 more … 64 sealed findings W_O — the pen combines them, and decides where each goes the page — added to, never erased then block n+1 reads this same page and adds its own note 80 blocks, 160 notes, one page, one 8,192-number total at the end

The two ideas in one picture. The projection is the pen and the residual stream is the page.

Section takeaways

  • Addition requires matching widths, which is the real reason d_model is 8,192 at every one of the 80 layer boundaries.
  • You cannot taper, widen or splice a differently-shaped block into the stack without a projection that restores the width.
  • The feed-forward branch widens to 28,672 internally and returns to 8,192 before the add, so the wide part never touches the stream.
  • The additive path also carries the training signal back to block 1 without being scaled 80 times.
  • Logit lens and activation patching work only because intermediate streams share a coordinate system with the final one.

Key takeaways

  • Concatenated head outputs are 64 sealed lists. Nothing has crossed between them, and the attention output projection is the only thing that ever will.
  • The mechanism is one matrix multiply. Each output number is a weighted sum of every input number, and the sum runs straight across the head boundaries because the arithmetic has no idea they are there.
  • W_O does three jobs in that one multiply: it combines findings, it excludes specific heads from specific outputs via learned zeros, and it routes each finding into a particular region of the residual stream.
  • Read a column for “which heads feed this output”. Read a row for “where does this head’s output land”. Slicing the rows into 64 blocks gives you per-head contributions, which is the same arithmetic written differently.
  • W_O is the same size as W_Q, four times the size of W_K and W_V together, and 44 percent of the attention block. That is proportionate to the number of decisions it stores.
  • Blocks add to the residual stream rather than replacing it, so nothing written early is ever erased and block 71 can still read block 3.
  • Addition requires matching widths, which is the real reason d_model is constant across all 80 layers, and it also provides the clean gradient path that makes 80 layers trainable.

Frequently asked questions

What does the output projection (W_O) actually do in multi-head attention?

It takes the concatenated outputs of all the heads and produces one vector of d_model numbers to add to the residual stream. In doing so it combines findings across head boundaries, excludes chosen heads from chosen outputs using learned zeros, and decides which region of the stream each finding is written into.

Why is W_O the same size as W_Q and so much bigger than W_K and W_V?

W_Q and W_O are both 8,192 x 8,192 because 64 heads times 128 dimensions equals d_model. W_K and W_V are 8,192 x 1,024 because grouped-query attention gives them 8 heads rather than 64, which shrinks the KV cache. The size of W_O is proportionate to its job: 8,192 recipes, each drawing on all 64 heads.

What would happen if you removed the output projection?

Each head’s output would land in its own fixed slice of the residual stream and stay there permanently. No two heads could ever be combined, and multi-head attention would degenerate into 64 unrelated operations sharing one container.

Is W_O applied to the concatenated heads or per head?

Both descriptions give identical results. Because it multiplies a concatenation, you can slice W_O into 64 blocks of 128 rows, multiply each head by its own block, and add the 64 results. That equivalence is what makes “this head’s contribution to the residual stream” a well defined quantity.

Why does d_model stay the same in every transformer layer?

Because each block adds its output to its input, and addition requires both sides to have the same number of elements. Every sublayer must therefore return exactly d_model numbers, which is why the feed-forward network widens to 28,672 internally and projects back down to 8,192 before the addition.

Does W_O have a bias term?

It depends on the family. Llama-class models omit biases on all four attention projections, while the original 2017 architecture and several other families include them. The bias makes no difference to the argument here, since it is a constant added after the mixing has already happened.

Sources and further reading

Next in the seriesPart 6. The Feed-Forward Network: Where a Transformer Keeps What It Knowscoming 14 Aug

Check your understanding

Take the 10 question quiz on this article

It opens in a panel and takes you one question at a time. You get a full report at the end: your score, the correct answer to anything you missed, why it is correct, and a link straight back to the section it came from. Hints are there if you want them. Nothing is stored, and you can retake it as often as you like.

  • 10 questions
  • 3 select all that apply
  • hint on every question
  • timed, no limit

The Output Projection: How 64 Attention Heads Become One Thought

Question 1 of 10

Elapsed 0:00

1 The 64 heads have finished and their outputs laid side by side already come to 8,192 numbers. Why is that still not one vector in any useful sense?

0 of 10 answered

Previous