Same input, three times
Self-attention is scaled dot-product attention where the queries, keys and values are all projections of one sequence.
Every position builds a query, compares it against every position's key, and takes a weighted average of every position's value.
The output has the same shape as the input, so these layers stack without any glue between them.
What it replaced, and why
A recurrent layer connects position to position through sequential steps.
In self-attention every pair of positions is one multiplication apart, so a dependency across 500 tokens is as direct as one across 2.
That also removes the sequential dependency: an RNN must compute position before , while self-attention computes the whole sequence as one matrix multiply.
That is the property that made training on very large corpora possible, and it matters more than the accuracy improvement did.
It has no idea what order things are in
- : any permutation matrix.
Permute the input and the output is permuted identically. Nothing inside the operation refers to position.
The set of tokens is all it sees, so "dog bites man" and "man bites dog" produce the same set of outputs in a different order, with no signal that the order changed.
This is not a flaw to be worked around, it is why positional encoding exists as a separate mechanism.
The causal mask
A decoder must not let position read position , or predicting the next token would be a lookup.
Adding this matrix before the softmax sends every forbidden weight to exactly zero afterwards.
It is upper-triangular, and it is the only difference between the attention in an encoder and the attention in a decoder.
One layer, in order
- Project the input into queries, keys and values.
- Multiply queries by transposed keys.
- Scale by the root of the head width, then add the mask.
- Softmax each row into weights that sum to one.
- Multiply by the values, and project the result back to the model width.