Queries, Keys and Values
Attention lets a model look up relevant information from anywhere in a sequence, and it does that lookup with three learned projections of the same input: a query describing what you're looking for, a key describing what each item offers, and a value carrying what gets returned when there's a match.
Prerequisites: Sequence-to-Sequence Encoder-Decoder Models, Softmax and the Log-Sum-Exp Trick
A plain Sequence-to-Sequence Encoder-Decoder Models model compresses an entire input sequence into one fixed-size context vector, and that bottleneck degrades badly on long sequences because everything has to be squeezed through one summary. The fix seems obvious in hindsight: instead of forcing the decoder to work from one compressed summary, let it look back at the original input sequence directly, at every step, and decide for itself which parts of the input are relevant right now. That "which parts are relevant" decision is exactly what attention computes, and queries, keys and values are the mechanism that makes the decision learnable rather than hand-coded.
The analogy: a librarian search
Imagine searching a library. You arrive with a query — what you're actually looking for, phrased in your own words ("books about mean reversion in pairs trading"). Every book on the shelf has a key — a short descriptor, like a catalog tag, that summarizes what that book is about, independent of what anyone happens to be searching for. You compare your query against every book's key and get a relevance score for each — high for a close match, low for an unrelated book. Then you don't walk away with the keys — you walk away with the actual value: the book's contents. Attention runs this exact search, numerically, at every position of a sequence, simultaneously: every position emits a query (what it's looking for), every position (including itself) offers a key (what it has to offer) and a value (what gets returned if selected), and the output is a blend of values weighted by how well each key matched the query.
The maths
Given a set of input vectors (each, say, a token or timestep's embedding), three learned weight matrices project each input into a query, key, and value:
In words: the same input vector produces three different roles by being multiplied by three different learned matrices — , , . These are what the network actually learns during training; nothing about "query" or "key" is hand-designed, only the mechanism that uses them is fixed.
For a given query , its attention score against every key in the sequence is a scaled dot product:
In words: measure how well query and key align via a dot product (large when the two vectors point in a similar direction, i.e. when they "match"), then divide by — the square root of the key dimension — purely to keep the scores from growing too large as increases, which would otherwise push the next step's softmax into a regime with vanishing gradients.
These scores across all are turned into weights that sum to 1 via softmax, then used to blend the values:
In words: normalize the scores into a probability-like distribution over all positions, then take a weighted average of every position's value vector using those weights. Position 's output is a blend of everyone's values, leaning heavily on whichever positions its query matched best. Unlike a fixed-size context vector, this readout can pull directly from any position in the sequence, however far away, with a weight the model computes fresh for every query — nothing forces distant information to decay the way it does in a recurrent chain.
Worked example 1: computing attention weights by hand
Take positions with 2-dimensional keys and a query . Keys: , , . Use , so .
Dot products: , , . Scaled scores:
Softmax over : exponentiate, , , , sum .
Position 1's key matched the query best (raw dot product 1, the highest), so it gets the largest weight, 0.434 — but position 3's key, only a partial match, still earns a meaningful 0.351, not zero. This is the whole point of softmax here: it's a soft, graded lookup, not a hard "pick the single best match and ignore everything else."
Worked example 2: blending values with those weights
Continue the example with values , , . The output is the weighted sum using the weights just computed, :
The output vector is not any single input's value — it's a genuine blend, dominated by (since it got the largest weight) but pulled toward and proportionally. Change the query and every weight recomputes fresh; there's no fixed routing, which is exactly what lets the same mechanism serve completely different lookups at every position, at every layer, without re-architecting anything.
, , are each just a learned linear map applied to the input, the same kind of matrix transform this explorer visualizes as a stretch and rotation of a shape. Attention's expressive power comes from three differently-trained transforms of the same input feeding into a similarity comparison, not from any one of them individually.
Query, key and value are three different learned linear projections of the same input. The query asks "what am I looking for," the key answers "what do I offer," and the dot product between them measures the match — but what actually gets returned and blended into the output is the value, a separate projection carrying the content itself, not the descriptor used to find it.
What this means in practice
This query-key-value lookup is the mechanism underneath every transformer, and by extension underneath most modern large language models and increasingly, sequence models used for price and order-flow forecasting. Its practical draw over a recurrent architecture is that any position can attend directly to any other position in one step, with no decay over distance — useful when a relevant piece of context (a macro print, a large block trade) could be arbitrarily far back in the window and needs to be found on its merits, not on its recency. Its cost is that comparing every query against every key is in sequence length, which is exactly the scaling problem that motivated the state-space alternatives in Mamba and Selective State Spaces.
The trap: forgetting the scaling term, or misunderstanding why it's there. Without it, dot products between high-dimensional query and key vectors can grow large in magnitude purely as a side effect of dimensionality (more terms summed in the dot product means larger typical magnitudes), which pushes softmax into a saturated regime where one weight goes to nearly 1 and the rest to nearly 0 — the "soft," graded lookup degenerates into a near hard-max, and gradients through that near-saturated softmax vanish, stalling training. The scaling isn't a minor numerical nicety; skipping it is a common, hard-to-diagnose source of training instability in from-scratch attention implementations.
Practice in interviews
Further reading
- Vaswani et al., Attention Is All You Need (2017)
- Bahdanau, Cho & Bengio, Neural Machine Translation by Jointly Learning to Align and Translate (2014)