Let every position look back at every other position — and weight what actually matters.
Scaled dot‑product attention, end to end — plus the three things people get wrong about it.
Before attention, a sequence model had to squeeze everything it had read into one fixed-size hidden state and carry it forward. Information decayed. Long-range links were lost.
Attention throws that bottleneck out. Instead of remembering, each position looks up what it needs, directly, from every other position — in a single parallel operation. Relevance stops being a function of distance and becomes a function of content.
All three are just learned linear projections of the same input: Q = XWq, K = XWk, V = XWv. The model learns how to ask, how to advertise, and what to hand over as three separate skills.
Split dmodel into h smaller subspaces, run attention independently in each, concatenate, project with Wo. Different heads reliably specialise — syntactic dependency, coreference, positional locality. One head can only express one relation per position; eight can express eight.
Self-attention: Q, K, V all from the same sequence — the sequence interrogating itself. Cross-attention: Q from one stream, K and V from another — a decoder querying an encoder. Translation, captioning, and retrieval-augmented models all live in that second case.
Every token scores every token: n² computations, n² memory for the score matrix. Doubling context length quadruples both. Essentially all of modern long-context work — FlashAttention, sparse and sliding-window patterns, linear-attention families — is an attack on that one exponent.
scaled_dot_product_attention(Q, K, V, mask=None) in NumPy. No frameworks. Shapes: (n, dk) in, (n, dv) out.√dk scaling and set dk=512. Print the max softmax weight. Watch it collapse toward 1.0 — that is saturation, felt rather than read.Why does attention need three projections rather than two? Specifically: what breaks if you set V = K and reuse the keys as the values?