Beyond shape preservation, name two things W_O does after head concat
Same topic, related formats. Practice these next.
Same topic, related formats. Practice these next.
Multi-head attention concatenates h head outputs of dim d_head back to d_model, then multiplies by an output projection W_O of shape (d_model, d_model). Many people see W_O as a 'shape-preservation' bookkeeping step, but it has substantive roles. Name two things W_O contributes beyond just preserving d_model, and explain why removing it tanks quality even when shapes still line up.
W_O does cross-head mixing (lets heads share residual directions) and learned per-head weighting (amplifies useful heads, suppresses noisy ones). Removing it preserves shape but kills both.
Imagine eight researchers writing reports into separate columns of a shared spreadsheet. Without W_O, every researcher's findings stay locked in their own column forever; nobody can build on anyone else's work. W_O is the editor who reads all eight columns and rewrites them into a single mixed document where insights from researcher 3 can reinforce insights from researcher 7, and where the editor can quietly suppress the column from researcher 5 if their work is mostly noise. The shape of the document is the same with or without the editor, but the quality is wildly different. Take the editor away and you lose both the cross-pollination and the quality control.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example.
Everything important, quickly.
Explain the per-head slice structure of the concatenated output, walk through how W_O lets heads mix across slices, show how column norms encode per-head weighting, connect to induction-head composition and head pruning, and close with parameter cost vs benefit.
import torch
import torch.nn as nn
class MultiHeadAttention(nn.Module):
def __init__(self, d_model: int, n_heads: int):
super().__init__()
self.d_model = d_model
self.n_heads = n_heads
self.d_head = d_model // n_heads
self.W_q = nn.Linear(d_model, d_model, bias=False)
self.W_k = nn.Linear(d_model, d_model, bias=False)
self.W_v = nn.Linear(d_model, d_model, bias=False)
# W_O does the cross-head mixing and per-head weighting.
self.W_o = nn.Linear(d_model, d_model, bias=False)
def head_importance(self) -> torch.Tensor:
# Per-head write strength: norm of the d_head-wide columns of W_O
# that read from each head's slice. Low norm = effectively pruned.
W = self.W_o.weight # (d_model, d_model)
return torch.tensor([
W[:, h * self.d_head : (h + 1) * self.d_head].norm()
for h in range(self.n_heads)
])Real products, models, and research that use this idea.
What an interviewer would ask next. Try answering before peeking at the approach.
Red flags and common mistakes that signal junior thinking. Click to expand.
Treating W_O as a 'shape-preservation' formality and missing that it is the only point in the attention sub-layer where head outputs can mix with each other.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.