Linear algebra for LLMsPart 5: Attention, one operation at a time

The causal mask

6 min

No looking ahead

A decoder predicts each token from the ones before it, so token ii may attend to tokens j≤ij \le i only. During training all positions are computed at once, so the future has to be hidden explicitly.

Write

Causal: token ii sees only j≤ij \le i.

The mask

0 on and below the diagonal, −∞-\infty above: the lower-triangular shape from Part 2. It’s added to the scores, so allowed scores pass unchanged.

Write

Mij=0M_{ij} = 0 if j≤ij \le i, −∞-\infty if j>ij > i.

Add it to the scaled scores

+=

“the” keeps only its own score; “cat” keeps two; “sat” keeps all three.

Softmax each row

−∞-\infty becomes exactly 0. Row “cat”: e0=1e^{0} = 1 and e2.83≈16.9e^{2.83} \approx 16.9, so the weights are 1/17.9≈0.0561/17.9 \approx 0.056 and 0.9440.944. Every row sums to 1. The shading shows where each query looks.

Write

A=softmax⁡ ⁣(QK⊤/dk+M)A = \operatorname{softmax}\!\big(QK^\top/\sqrt{d_k} + M\big), row by row.

✏️ Your turn

Which weights?

masked row for “cat”:\text{masked row for “cat”:}

Which weight in this row is exactly 0? Which of the other two is bigger, and roughly how much bigger?

Work it out on paper, then go to the next card to check.

Answer

The masked one (key “sat”) is exactly 0. “cat” beats “the” by a factor of e2.83≈17e^{2.83} \approx 17: a gap of 2.83 in score.

Why not zero the weights afterwards?

softmax of the unmasked row “the” then zero the future sums to 0.33

Zeroing after the softmax leaves a row that no longer sums to 1: “the” would pass on only a third of its value. Adding −∞-\infty before the softmax makes the remaining weights renormalize among themselves.

Write

Mask before the softmax (add −∞-\infty), never after.

In PyTorch

mask = torch.ones(T, T, dtype=torch.bool).tril()
scores = scores.masked_fill(~mask, float("-inf"))
weights = scores.softmax(dim=-1)
# or all at once:
out = F.scaled_dot_product_attention(q, k, v, is_causal=True)

📌 Recap

The causal mask in one card

  • Mask: 0 on and below the diagonal, −∞-\infty above, added to the scaled scores.
  • Softmax each row: future weights become exactly 0, the rest sum to 1.
  • Example rows of AA: [1,0,0][1, 0, 0], [0.056,0.944,0][0.056, 0.944, 0], [0.14,0.58,0.28][0.14, 0.58, 0.28].
  • Mask before the softmax, not after.

Write

The four lines above.