4.1.11 · D3Transformer Architecture

Worked examples — Masked attention for autoregression

2,338 words11 min readBack to topic

Before we start, one word we lean on constantly:

The mask adds to every cell above the diagonal (the future) and everywhere else. After softmax those cells become exactly . That is the whole machine. Now let us exhaust it.


The scenario matrix

Every situation the causal mask can meet falls into one of these cells. Each row is a "case class"; the last column names the example that nails it.

# Case class What is unusual about it Worked in
A First row () Only one visible token — softmax over a single number Example 1
B Last row () Full past visible, nothing masked Example 2
C Middle row () Some past, some masked future Example 3
D Degenerate Whole sequence is one token Example 4
E Ties in scores Two allowed positions have equal Example 5
F Limiting value One masked cell is huge / one allowed cell dominates Example 6
G Real-world word problem Generation loop, next-token prediction Example 7
H Exam twist / trap Mask applied after softmax (the wrong way) Example 8

The numbers below reuse one small running example so you can watch the mask act on the same data across cases. We fix (so ) and this un-masked score matrix for :

(This is exactly the matrix from Example 2 of the parent note, rounded to two decimals.)

Figure — Masked attention for autoregression

Look at the picture: the red cells are the future — the mask will erase them. The green staircase is what each row is actually allowed to see. Notice the staircase grows by one cell per row. That growth is autoregression.


Worked examples

Example 1 — Cell A: the very first row

  1. Write the raw row. Row 1 of is . Why this step? We always start from the un-masked scores, then let the mask decide what survives.

  2. Apply the mask. For , only is allowed, so columns 2 and 3 get : Why this step? Token 1 is generated first; there is literally no past and no permitted future, so it can only attend to itself.

  3. Softmax. , so Why this step? Softmax turns scores into weights summing to 1. With one survivor the answer is forced: it must be .

Verify: a softmax over exactly one live entry is always , regardless of that entry's size — because . The output : the first token attends purely to itself. ✅


Example 2 — Cell B: the last row, nothing masked

  1. Raw row. Row 3 is . Why this step? Same starting point; the mask will simply add everywhere here.

  2. Apply the mask. For , all are allowed, so adds — the row is unchanged. Why this step? The last token's "future" is empty, so masking removes nothing. This is the one row where causal attention and full attention agree.

  3. Softmax. Using , : Why this step? Convert to a probability distribution over the three visible tokens.

Verify: ✅ — and the two equal scores () yield two equal weights (), a sanity check that softmax preserves ties (we press on this in Example 5). Answer confirms: for the last row masked attention = standard attention.


Example 3 — Cell C: a middle row, half masked

  1. Raw row. Row 2 is . Why this step? Column 3 has a high raw score () — a perfect chance to see the mask do real work by deleting a tempting future cell.

  2. Apply the mask. For , is future : Why this step? Even though column 3 scored high, it is the future. The mask must zero it or the model would cheat by copying the answer.

  3. Softmax over the two survivors. , , sum : Why this step? The two live scores compete; the higher one (column 1) wins the larger share.

Verify: ✅. The masked column contributes exactly , so — no leakage from . ✅


Example 4 — Cell D: the degenerate one-token sequence

  1. Build the mask. is with (the diagonal is always allowed). Why this step? The diagonal is never masked — a token may always attend to itself (this is Mistake 3 in the parent note).

  2. Softmax over one entry. . Why this step? Same forced-to-one logic as Example 1, now for the whole matrix.

Verify: the weight is for any ; the value of never enters the answer. Output is . A one-token sequence is a fixed point of masked attention — nothing to leak, nothing to weigh. ✅


Example 5 — Cell E: exact ties among allowed positions

  1. Confirm the mask leaves both ties alive. Columns 1 and 2 are , so both survive; only column 3 is . Why this step? We want to isolate the effect of ties, not of masking, so we make sure the mask does not break the tie for us.

  2. Softmax. for each; sum : Why this step? Softmax is symmetric — equal inputs give equal outputs. The masked cell still contributes .

Verify: ✅ and the two weights are bit-for-bit equal. Ties split evenly; the mask does not disturb this. ✅


Example 6 — Cell F: limiting behaviour (a dominating cell)

  1. Compute exactly. , , sum : Why this step? We test the softmax at an extreme so we can see its limiting shape.

  2. Read the limit. As the gap , the weights approach — softmax becomes a hard "argmax". Why this step? This tells us how masking interacts with confidence: a very sharp distribution is fine, and a masked is just the extreme case of a very small score forced to weight .

Verify: ✅. And notice a masked cell () is exactly this limit taken all the way: , contributing precisely — the mask is "the argmax limit for the future." ✅


Example 7 — Cell G: a real generation loop

  1. List the query's allowed keys. Row allows , i.e. columns 1–6. But column 6 is the token we are predicting — it is not yet generated. Why this step? During generation the future simply doesn't exist, so there is nothing to mask beyond what already isn't there. Compare with training, where all 6 tokens sit in the buffer and the mask must actively hide column 6 to prevent copying.

  2. Suppose the (already scaled) visible scores over columns 1–5 are . Softmax them: ; sum . Why this step? This is the actual distribution the model uses to weight before producing "Paris". "France" (column 4) dominates — exactly the context that should trigger "Paris".

  3. Predict. The blended value feeds the output layer, which emits "Paris". No cell for token 6 appears — the answer was inferred, never copied. Why this step? This is the whole payoff of masking: training with the mask made the model behave identically to this leak-free inference loop (teacher forcing supplied the ground-truth prefix during training).

Verify: (rounding) ✅ and the largest weight sits on "France", the semantically correct cue. ✅


Example 8 — Cell H: the exam trap (mask after softmax)

  1. Softmax first. ; sum : Why this step? This is the (wrong) order the student used.

  2. Zero the future with the binary mask. Multiply by : Why this step? The masked weight is removed, but nobody re-scaled the rest — the distribution now leaks probability mass, summing to , not .

  3. Contrast with the correct order. Applying before softmax gives , which does sum to 1. Why this step? Masking before softmax renormalizes automatically — the denominator only sums the survivors. That is why the parent note insists on -before-softmax, not -or--after (Mistake 1).

Verify: wrong order sums to ✅ (trap confirmed); correct order sums to ✅.


Recall

Recall Which rows of the mask actually delete a cell?

Every row except the last ::: row masks columns ; the last row () has no future, so nothing is deleted (Example 2).

Recall A softmax over a single surviving score always equals…

::: because regardless of (Examples 1 and 4).

Recall Why is the diagonal never masked?

A token must be able to attend to itself for self-reference ::: masking hides only future positions , never the current one (Example 4).

Recall What breaks if you mask after softmax with a 0/1 mask?

The weights no longer sum to 1 ::: e.g. sums to ; you'd have to renormalize by hand (Example 8).

Related: Decoder Architecture, Encoder-Decoder Models, Positional Encoding.