Attention Mechanisms
Turn compatibility scores into attention weights, then combine values. Explore the geometry, normalization, and limits of the mechanism.
Jump to a section
Why this matters
Attention lets each position combine information from other positions using learned compatibility scores. A query is compared with keys, softmax turns the scores into weights, and those weights combine the value vectors.
Think of it as a soft key-value lookup. The useful questions are what gets scored, which positions are allowed to contribute, and how the resulting values are mixed.
Build the mental model
Think of a soft key-value store. Each token emits three vectors:
- a query (
q): "what am I looking for?" - a key (
k): "what do I offer?" - a value (
v): "what I'll hand over if you attend to me."
For a given query, you score it against every key (dot product = similarity), turn those scores into a probability distribution with softmax, and return the weighted sum of the values. A hard dictionary returns exactly one value for an exact key match; attention returns a blend, weighted by match strength, which is what makes it differentiable and trainable.
Trace scaled dot-product attention
Q and K determine row weights; those weights combine V into the output.
Exact inputs and equations appear with the figure.
Preparing the scientific figure…
One exact head with authored 4×2 Q, K, and V tensors. The 3D view shows its computed weight matrix. Learned input/output projections, multi-head concatenation, dropout, and FlashAttention tiling are omitted.
Vaswani et al. · Attention Is All You Need§3.2.1, Equation (1), Figure 2
Original schematic of the published operations. The tensors are small authored examples, not the paper’s experimental model.
Experiment with related Studio inputs
Lower temperature to concentrate the weights. Raise it to distribute them more evenly. Which token keeps the largest share?
Fixed illustrative scores. This isolates softmax weighting; it does not compute QKᵀ, masking, or the weighted value vectors.
"Self-attention" means Q, K, and V are projected from the same sequence. Each token can attend to positions allowed by the mask; causal self-attention excludes future positions.
Work through the math
Scaled dot-product attention, for queries , keys , and values :
The softmax is taken row-wise, so each query's attention weights sum to 1. Why divide by ? If the components of and are independent with mean 0 and variance 1, their dot product has variance . For large , the raw scores grow large in magnitude, pushing softmax into regions where its gradient is almost zero (it saturates toward a one-hot vector). Scaling by normalizes the variance back to ~1, keeping gradients healthy.
Key takeaway: Attention is a soft, differentiable dictionary lookup. The divisor counters dimension-dependent score growth under the assumptions above; it does not guarantee unit variance or prevent saturation for arbitrary learned Q and K.
Multi-head attention runs attention operations in parallel on lower-dimensional projections, then concatenates:
Each head can learn a different weighting; interpretable specializations are possible, not guaranteed. With , multi-head costs roughly the same as a single full-width head. With equivalent Q/K/V and output projections, both have projection weights, excluding biases. Splitting the width across heads does not add parameters.
| Variant | Key idea | Tradeoff |
|---|---|---|
| Single-head scaled dot-product | One softmax weighting per query | All value dimensions use the same weighting |
| Multi-head (MHA) | parallel heads on low-dim projections, concatenated | Multiple weightings; similar FLOPs and the same projection parameter count at fixed total width |
| Multi-query / grouped-query (MQA/GQA) | Share K/V heads across query heads | Smaller KV cache; quality tradeoff depends on architecture and training |
| FlashAttention | Exact attention, tiled to avoid materializing the matrix | Same math, far less memory traffic, not an approximation |
Read the implementation
1import torch
2import torch.nn.functional as F
3from torch import Tensor, nn
4
5
6def scaled_dot_product_attention(
7 q: Tensor, k: Tensor, v: Tensor, mask: Tensor | None = None
8) -> Tensor:
9 # q,k,v: (batch, heads, seq, d_k); each mask row must allow at least one key
10 d_k = q.size(-1)
11 scores = (q @ k.transpose(-2, -1)) / d_k**0.5 # (b, h, seq, seq)
12 if mask is not None:
13 scores = scores.masked_fill(mask == 0, float("-inf")) # causal / padding
14 weights = F.softmax(scores, dim=-1)
15 return weights @ v # (b, h, seq, d_k)
16
17
18class MultiHeadAttention(nn.Module):
19 def __init__(self, d_model: int, n_heads: int) -> None:
20 super().__init__()
21 assert d_model % n_heads == 0, "d_model must be divisible by n_heads"
22 self.n_heads, self.d_k = n_heads, d_model // n_heads
23 self.qkv = nn.Linear(d_model, 3 * d_model) # fused Q,K,V projection
24 self.out = nn.Linear(d_model, d_model)
25
26 def forward(self, x: Tensor, mask: Tensor | None = None) -> Tensor:
27 b, seq, _ = x.shape
28 qkv = self.qkv(x).view(b, seq, 3, self.n_heads, self.d_k)
29 q, k, v = qkv.permute(2, 0, 3, 1, 4) # each: (b, heads, seq, d_k)
30 out = scaled_dot_product_attention(q, k, v, mask)
31 out = out.transpose(1, 2).reshape(b, seq, -1) # recombine heads
32 return self.out(out)
33
34
35# quick shape test
36mha = MultiHeadAttention(d_model=512, n_heads=8)
37x = torch.randn(2, 10, 512)
38assert mha(x).shape == (2, 10, 512)Questions and trade-offs
- Conceptual: Why does attention scale scores by , and what fails if you don't? (Variance of the dot product grows with ; unscaled scores saturate softmax and kill gradients.)
- Implementation: How do you implement a causal mask, and where in the computation does it go? (Set future positions to in the score matrix before softmax, so their weights become 0.)
- Applied: What's the time and memory complexity of self-attention in sequence length , and why is that a problem for long contexts? (Dense attention takes arithmetic, plus projections. A naive implementation stores quadratic score matrices; FlashAttention avoids storing them in device memory but retains quadratic arithmetic. Sparse and linear variants change the attention computation.)
- Systems-level: What does the KV cache do at inference, and why does it make autoregressive decoding cheaper? (It reuses past keys/values. Dense projections for the new token cost per layer; its attention over a prefix of length still costs .)
- Failure modes: Why use multiple heads instead of one wide head? (Separate subspaces let heads attend to different relations simultaneously; a single softmax can only express one weighting per query.)
Check your understanding
Close this page. Derive scaled dot-product attention from scratch: write the formula, state the shapes of , , , explain the term, and describe in one sentence how multi-head differs. Then check what you missed against Stage 3.
Sources and further reading
- Vaswani et al., Attention Is All You Need, §3.2: attention equations, head dimensions, and projection shapes.
- Dao et al., FlashAttention: exact attention with reduced memory traffic.
Oliver Perrin
Machine Learning Engineer · Founder, LiminalML
LiminalML brings together concept explanations, mathematical examples, and working visuals. Find more writing by Oliver on the LiminalML Substack.
Keep exploring the idea.
Ask a follow-up in a guided session, work through the self-check, or open the visual in Studio to build on it.
Related concepts
Deep Learning
Transformer Architecture
Follow attention, feed-forward layers, normalization, and residual connections through a Transformer block.
LLMs
KV Cache
See which token projections caching saves, what attention must still read, and how memory use grows with context.
Deep Learning
Batch Normalization
Normalize activations across a batch, apply a learned scale and shift, and understand why training and evaluation behave differently.