Scaled dot-product attention
Take the attention head from §4.2, make it the size real models use, say , initialize it the standard way so that queries and keys have unit-variance entries, compute the scores as exactly as that section did, and look at the attention weights before any training. Most rows are nearly one-hot. Each query has already "decided" on a single key, at random, and the gradient flowing back through the softmax is close to zero. The head cannot learn, because it is stuck in the hard lookup that §4.1 worked so hard to escape.
The fix is one division, and it is the reason the formula in every Transformer paper looks the way it does,
This section derives the from a variance argument, shows exactly how the gradient dies without it, and then does the thing every lab interview eventually asks for. We derive the backward pass of attention by hand and check it against numerical gradients.
The formula, piece by piece
Fix one head. The queries are , the keys , and the values , as in §4.2 (a batch dimension, and later a head dimension, ride along in front). Scaled dot-product attention computes three matrices,
where the softmax acts on each row of separately, so and every row of sums to 1.
In plain words, score every query against every key, shrink the scores by the square root of the key width, turn each query's scores into weights, and average the values with them.
In the language of §4.1, dividing by is a soft lookup at temperature . The question is why that particular temperature.
Why dot products grow with the width
Suppose that at initialization the entries of a query and a key are independent random variables with mean 0 and variance 1. This is roughly true in a freshly initialized network whose inputs have been normalized (LayerNorm, §5.2) and whose projections use a variance-preserving initialization (§0.7). The score is a sum of products,
Each term has mean by independence. Its variance is
The terms are independent of each other (they involve different coordinates), so their variances add,
In plain words, the typical size of a raw score is . Double the key width and the scores grow by a factor of , for no reason other than that there are more terms in the sum.
Dividing by undoes exactly that growth, since . The scaled scores have unit variance at every width. (If the entries have variances and instead of 1, the same steps give , and the scaling still removes the dependence on .) This is the argument in footnote 4 of Vaswani et al. (2017), which also notes that additive attention outperformed unscaled dot-product attention at large . It is also Fact 1 of §1.3 in a new role. There it explained why random vectors are nearly orthogonal. Here it explains why their raw dot products are large.
What large scores do to the softmax
Why should we care that scores have standard deviation rather than 1? Because softmax only sees differences between scores, and when the differences are large the softmax saturates. If the largest score in a row beats the runner-up by 10, the winner's weight is at least , which for keys is 0.9986. The lookup has become hard, and §4.1 told us that a hard lookup has no gradient. To see how little gradient is left, we need the derivative of the softmax as a matrix.
The Jacobian of softmax, and what saturation does to it
Write one row of scores as and its softmax as . §0.2 derived the softmax Jacobian with the quotient rule (and §4.1 used its entries, ). As a matrix,
Recall its three properties from that section. It is symmetric, its rows sum to zero (shift invariance again), and it is positive semidefinite, because for any
the variance of the numbers when entry is chosen with probability . Two consequences matter for attention.
The first is a single number for how much gradient can pass. The trace of the Jacobian, the sum of its eigenvalues, is . It is largest, , for uniform weights, and it shrinks to 0 as the weights concentrate.
The second is the punchline. If is one-hot, then every variance under is zero, so the quadratic form vanishes for every , and a symmetric positive semidefinite matrix with a zero quadratic form is the zero matrix. A saturated softmax has a zero Jacobian. No gradient reaches the scores, and therefore none reaches or . The head's attention pattern is frozen wherever it happened to land at initialization, exactly the stuck query of Exercise 4.1e.
In backpropagation we never build this matrix. We only need its product with the upstream gradient , the vector-Jacobian product you wrote in Exercise 0.2c,
In plain words, each score's gradient is its weight times how much its upstream gradient exceeds the weighted average upstream gradient. With a one-hot , the winner's term is and every other term has weight 0, which is the punchline again, in one line.
Saturation, measured
Now we can measure what scaling buys. For each width, draw random queries and 32 random keys, compute the attention weights with and without the division by , and record the largest weight in each row and the trace of the softmax Jacobian (, which is 0 for one-hot rows).
Without scaling, the average largest weight climbs from 0.35 at to 0.96 at , and the gradient capacity (the trace) falls more than tenfold. With scaling, both numbers stay put at every width, about 0.16 and 0.93. The head starts out soft whatever its size, and its sharpness becomes something it learns rather than an accident of .
Saturation has a mirror image. If scores are tiny compared to 1, the weights are nearly uniform, , and by the formula of §4.1 each score receives a gradient of order . Unit-variance scores sit between the two extremes, soft enough for every key to receive gradient and sharp enough that the weights are not all the same.
The assumption behind the argument, and when it fails
The variance argument assumes that queries and keys are independent. That is true at initialization and false after training, because the whole point of learning and is to make the query of "it" align with the key of "animal". Suppose a key is correlated with its query, with independent noise. Then , so the scaled score has mean , which still grows with width (Exercise 4.3d derives the variance too). Aligned vectors have dot products that grow like , by the law of large numbers, not like .
This is why the Maximal Update Parametrization (P) of Yang et al. (2022) scales attention scores by instead of . Their analysis of how quantities evolve during training, as width grows, predicts that queries and keys become correlated, and is the scaling that keeps the logits of a trained model stable across widths, which is what makes hyperparameters transfer from small models to large ones (§9.5). Other practical answers to growing logits include normalizing queries and keys before the dot product, QK-norm (Henry et al. 2020). Dehghani et al. (2023) adopted it for their 22-billion-parameter ViT after finding that, already at about 8 billion parameters, attention logits grew to huge values, the weights became nearly one-hot, and training diverged after a few thousand steps (§5.7). And some implementations fold the into the initialization of rather than into the forward pass. T5's is one. Its query weights are initialized with a standard deviation smaller by a factor of than its key weights, and the scores are never divided. At initialization the two choices are identical. During training they differ slightly, because an optimizer such as Adam takes steps of a similar size whatever the scale of a weight, so the effective learning rate of the folded-in version is different.
| choice | scores at init | idea | used by |
|---|---|---|---|
| no scaling | std | none, saturates at large | early dot-product attention (Luong et al. 2015) |
| std 1 | keep logits unit-variance at init | the original Transformer and nearly every LLM | |
| std | keep trained, correlated logits stable across width | P | |
| scale folded into init | std 1 | same as , no division in the forward pass | T5 |
| QK-norm | bounded | normalize and , often with a learned gain | ViT-22B, several recent LLMs |
Scaled dot-product attention with an optional mask
This is the most-asked coding question in the field. Implement scaled_dot_product_attention(Q, K, V, mask=None) for inputs of shape (..., T_q, d_k), (..., T_k, d_k), and (..., T_k, d_v) with any number of leading batch dimensions. mask, if given, is a boolean array broadcastable to (..., T_q, T_k) in which True means "may attend" (the PyTorch convention). Assume every query may attend to at least one key (§4.4 handles the other case). Return (O, A). It must be numerically stable and must give masked positions a weight of exactly zero.
A vectorized implementation, and why stability is not optional
Here is the version we will use for the rest of the chapter. Every line is one equation from above.
The naive line fails in float16 for a score of only 12, because exceeds the largest float16 number, 65,504 (the cutoff is ). In float32 the cutoff is about 88.7. Subtracting the row maximum fixes overflow completely, because the largest exponent becomes and the denominator is at least 1. Small exponents can still underflow to zero, but that is harmless, since those weights really are negligible. This is why production kernels subtract the maximum, and why mixed-precision training usually computes the softmax and its normalizer in float32 even when the matrix products run in bfloat16 or float16 (§8.5). FlashAttention goes one step further and computes the maximum and the normalizer incrementally, block by block, so the score matrix never has to exist in memory (§12.2).
The backward pass of attention
Now the derivation that separates people who have used attention from people who understand it. Given the upstream gradient , we want , , and . (Here always means , a matrix of the same shape as , the convention of the FlashAttention papers.) Write for the scale. The forward pass is three steps,
and we walk back through them in reverse, using index notation so that no step is a leap. Recall from §0.2 the rule for any product , namely and . Each step below is that rule, checked by indices.
Step 1, through . Entry by entry, . The entry appears in for every query , with coefficient , so
The entry appears in for every , with coefficient , so
Step 2, through the row-wise softmax. Each row of depends only on the same row of , so we apply the softmax vector-Jacobian product above to every row,
The row sum simplifies nicely. Substituting ,
so is just the dot product of row of with row of , and
Step 3, through . Entry by entry, . So appears in for every key , with coefficient , and appears for every query , with coefficient ,
In plain words, the value gradient is the attention-weighted sum of output gradients, the score gradient is the softmax backward applied to , and the query and key gradients come from the score gradient exactly as in any matrix product, times the scale.
Four observations make this derivation useful in practice.
- Masks need no special handling. A masked entry has , so automatically, and no gradient leaks through a masked connection.
- The backward pass costs about twice the forward pass. The forward pass does two large matrix products ( and ). The backward pass does four (, , , ), each the same size. This is the attention version of the familiar rule that a backward pass costs twice a forward pass (§5.6).
- The backward pass needs , a matrix per head. Storing it for every layer is what makes naive attention memory-hungry (§4.7). FlashAttention instead stores only and one number per row, the log-sum-exp of the scores, and recomputes block by block during the backward pass (§12.3).
- The identity matters. Computing from its definition needs a whole row of and at once. Computing it from and needs neither, which is exactly what lets FlashAttention's backward pass work one tile at a time.
The backward pass of attention, checked numerically
Implement attention_backward(Q, K, V, dO, mask=None) returning (dQ, dK, dV) for single-head scaled dot-product attention with Q of shape (T_q, d_k), K of shape (T_k, d_k), V of shape (T_k, d_v), upstream gradient dO of shape (T_q, d_v), and an optional boolean mask (True means attend, every row has at least one True). Recompute the forward pass inside the function. The tests compare your gradients with central finite differences of .
How big are the scores of aligned queries and keys?
Let , let be independent of it, and let for a correlation . Derive the mean and variance of the scaled score in closed form, and implement scaled_score_moments(d_k, rho) returning (mean, var). The tests check your formula against simulation. Then explain, in a comment, what your formula says about versus scaling.
In PyTorch
PyTorch's scaled_dot_product_attention computes exactly our formula, and dispatches to a fused FlashAttention or memory-efficient kernel when one is available. It also takes dropout_p, which during training zeroes attention weights at random and rescales the rest, as GPT-2 and BERT do at a rate of 0.1. Most recent large language models train with it set to zero. Below we check the function against our NumPy version, then check our hand-derived backward pass against autograd.
Read more
- Vaswani et al. (2017). Attention Is All You Need. Section 3.2.1 and its footnote give the variance argument for the scaling.
- Phuong & Hutter (2022). Formal Algorithms for Transformers. Algorithm 4 states scaled dot-product attention with masks precisely, in the same notation style as this chapter.
- Dao et al. (2022). FlashAttention. Appendix B derives the same backward pass, including the identity, and shows how to run it tile by tile.
- Yang et al. (2022). Tensor Programs V. The P paper, which argues for attention scaling.
- Henry et al. (2020). Query-Key Normalization for Transformers and Dehghani et al. (2023), Scaling Vision Transformers to 22 Billion Parameters. Normalizing queries and keys, and the logit growth that made it necessary.
- Milakov & Gimelshein (2018). Online normalizer calculation for softmax. Computing a stable softmax in one pass, the seed of FlashAttention.