Ask a large language model anything and, underneath, it does one thing over and over: it reads the tokens so far and outputs a probability for every token that could come next. Choose one, append it, repeat. Training, perplexity, attention and the KV cache all follow from taking that loop seriously. The GPT-2 report states the starting point in one line.
Spotted in the wild
- “x before t”The prefix: every token before position .
- “p theta of x t given the prefix”The model's next-token distribution at position .
- “z t, the logits”One real score per vocabulary token at position .
- “softmax of z, entry i”Exponentiate and normalise: .
- “script L, the loss”Cross-entropy: the mean negative log-likelihood per token.
- “perplexity”: the effective number of tokens the model is choosing between.
- “query i, key j, value j”Projections used to score position for position , and to average.
- “d k”Dimension of queries and keys; scores are divided by .
- “the causal mask”when and when , added to the scores before the softmax.
- “size of the vocabulary”The number of classes in every next-token prediction.
- “N, the parameter count”A forward pass costs about FLOPs per token.
| Symbol | Say it | Meaning | LaTeX |
|---|---|---|---|
| “x before t” | The prefix: every token before position . | ||
| “p theta of x t given the prefix” | The model's next-token distribution at position . | ||
| “z t, the logits” | One real score per vocabulary token at position . | ||
| “softmax of z, entry i” | Exponentiate and normalise: . | ||
| “script L, the loss” | Cross-entropy: the mean negative log-likelihood per token. | ||
| “perplexity” | : the effective number of tokens the model is choosing between. | ||
| “query i, key j, value j” | Projections used to score position for position , and to average. | ||
| “d k” | Dimension of queries and keys; scores are divided by . | ||
| “the causal mask” | when and when , added to the scores before the softmax. | ||
| “size of the vocabulary” | The number of classes in every next-token prediction. | ||
| “N, the parameter count” | A forward pass costs about FLOPs per token. |
One classification problem per position
The chain rule of probability is exact for any sequence of tokens:
No Markov assumption hides here. An -gram model truncates the history; a transformer conditions on the whole prefix that fits in its context window. Language modelling is therefore classification problems over the vocabulary , one per position. From the prefix the network computes logits , and the softmax turns them into a distribution:
In code, the output at position is the prediction for token , which is why the targets are the inputs shifted left by one. Adding the same constant to every logit changes nothing, because . Only differences between logits matter, so implementations subtract the largest logit before exponentiating and nothing can overflow:
def log_softmax(z):
m = z.max(axis=-1, keepdims=True) # shift invariance: subtract the max
return z - m - np.log(np.exp(z - m).sum(axis=-1, keepdims=True))
A three-token vocabulary has logits . What probability does softmax give the first token? (Subtract 1 from every logit first.)
Cross-entropy and teacher forcing
Training maximises the likelihood of real text, which is the same as minimising the mean negative log-likelihood, the cross-entropy loss:
For one position with target , the loss is , and its gradient is : predicted probabilities minus the one-hot target. Each wrong token's logit is pushed down in proportion to the probability it took.
During training the model conditions on the true prefix, never on its own guesses. This is teacher forcing, and together with the causal mask below it lets one forward pass score all positions in parallel. At generation time the model must condition on its own samples instead, so early mistakes can compound (sometimes called exposure bias).
A useful check: a freshly initialised model predicts nearly uniformly, so its loss should start near . A first logged loss far above that points at the initialisation or the loss code.
A freshly initialised model with a vocabulary of 50,257 tokens predicts almost uniformly. Near what cross-entropy, in nats per token, should training start?
Perplexity, bits and compression
Perplexity is the exponential of the cross-entropy, the reciprocal of the geometric-mean probability of the observed tokens:
A model that gives every token probability has , so its perplexity is exactly : perplexity is the effective number of tokens the model is choosing between, and a perfect model scores 1. Dividing by gives bits per token, and the bits are literal. An arithmetic coder driven by the model's probabilities encodes a text in about bits, within a couple of bits for the whole message, so a better predictor is a better compressor (Delétang et al., 2024).
| Quantity | Formula | Uniform model over tokens |
|---|---|---|
| Cross-entropy, nats per token | ||
| Bits per token | ||
| Perplexity | ||
| Bits per byte | total bits divided by bytes of text | depends on the tokeniser |
Per-token perplexity depends on the tokeniser: splitting the same text into fewer, longer tokens raises it without changing how well the text is predicted. Compare models on the same text in bits per byte, with the same context length, and remember that perplexity measures prediction, not helpfulness or truth.
A model assigns probabilities , and to the three tokens of a text. What is its perplexity on that text?
The decoder-only transformer
In most current LLMs, the network that computes is a stack of identical blocks:
tokens x_1 … x_T
→ embedding lookup: one row of a |V| × d table per token (chamber 1)
→ positional information (learned vectors, or RoPE inside attention)
→ L blocks, each:
h ← h + Attention(Norm(h)) mixes information across positions
h ← h + MLP(Norm(h)) processes each position on its own
→ final Norm → unembedding (d × |V|) → logits z_t
Attention is the only place where positions exchange information. Residual connections let each block add a correction to the stream rather than replace it, and normalising before each sublayer (pre-norm, as in GPT-2; many newer models use RMSNorm) keeps deep stacks trainable. Apart from the mask, attention scores ignore token order, so position is injected explicitly: GPT-2 adds a learned vector per position, while rotary embeddings, RoPE (Su et al., 2021), rotate each query and key by an angle proportional to its position so that depends on the relative offset. Open-weight families such as Llama, Mistral and Qwen use RoPE.
Each block holds about parameters in attention and in an MLP with a hidden layer, so without embeddings (Kaplan et al., 2020). For GPT-2 small, , and give million; position embeddings, biases and norms bring it to the 124 million of the released checkpoint.
Scaled dot-product attention, step by step
Let be the input at position . One attention head projects it three ways: a query (what this position looks for), a key (what position can be found by) and a value (what position hands over), with .
- Score each position: .
- Mask the future: add for (and 0 otherwise), so position cannot see the tokens it must predict.
- Normalise: . Masked entries get , exactly.
- Average the values: .
Stacking the rows into matrices gives the whole layer in one line:
def causal_attention(Q, K, V):
T, d_k = Q.shape
S = Q @ K.T / np.sqrt(d_k) # (T, T) scores
S[np.triu_indices(T, k=1)] = -np.inf # mask j > i
A = np.exp(S - S.max(axis=1, keepdims=True))
A /= A.sum(axis=1, keepdims=True) # each row sums to 1
return A @ V
Three facts are worth knowing cold. The weights in each row are nonnegative and sum to 1, so every output lies in the convex hull of the visible values: attention blends, it never extrapolates. If the components of and are independent with mean 0 and variance 1, then has variance ; without the division, wide heads would push the softmax into nearly one-hot regions with tiny gradients. And multiplying a query by multiplies every score by , which is a softmax temperature of in disguise. Temperature returns, applied to the output logits, in the chamber on sampling.
In a causal decoder, what attention weight does the query at position 3 place on position 5?
Multi-head attention runs heads in parallel, each with its own projections to dimensions, concatenates their outputs and mixes them with , at about the cost of one full-width head. Heads specialise: one may attend to the previous token, another may find an earlier copy of the current token and look at what followed it (an induction head). Grouped-query attention (Ainslie et al., 2023) lets several query heads share one key–value head, which shrinks the cache below.
Generation: prefill, decode and the KV cache
Generation runs the opening loop: compute logits at the last position, choose a token (greedily, or by sampling with temperature, top-k or top-p, which is the subject of the sampling chamber), append it, repeat. It has two phases. Prefill processes the whole prompt in one parallel pass. Decode then produces one token per forward pass, and each new query must attend to the keys and values of every earlier position.
Because of the causal mask, earlier positions never see later tokens, so their keys and values never change. The model therefore stores them. The KV cache holds and for every layer, head and position so far; a decode step computes for the new token only, appends its and attends over the cache. Without it, every step would reprocess the whole prefix: generating tokens after a prompt of would take about token passes instead of .
| Prefill | Decode step | |
|---|---|---|
| Tokens processed | the whole prompt, in parallel | one |
| Weight-matrix work | about FLOPs per prompt token | about FLOPs |
| Attention work | quadratic in prompt length | linear in current length |
| Usually limited by | arithmetic | reading weights and cache from memory |
The comes from one multiply and one add per parameter; Kaplan et al. write the whole forward pass as FLOPs per token. Over a context of length the score matrices have entries per head and layer, so attention's total cost is quadratic in . Kernels such as FlashAttention (Dao et al., 2022) avoid storing those matrices but still do the quadratic arithmetic. The cache costs numbers per token; the chamber on running models turns that into gigabytes.
Roughly how many GFLOPs does an 8-billion-parameter model spend on the matrix work for one generated token?
Read beyond
Book · free online · ~25 min
Speech and Language Processing (3rd ed. draft)Dan Jurafsky & James H. Martin · Chapter “N-gram Language Models”: evaluating language models and perplexity
Work through the perplexity examples and check that a uniform model over a vocabulary of size V scores exactly V.
Book · free online · ~25 min
Dive into Deep LearningZhang, Lipton, Li & Smola · Section 11.3: attention scoring functions and the masked softmax
Compare their masked softmax, which uses a large negative number, with setting masked scores to minus infinity.
Article · free online · ~30 min
The Illustrated GPT-2 (Visualizing Transformer Language Models)Jay Alammar · Parts 1 and 2: the decoder stack and masked self-attention
Trace one token through the stack and name the matrix that produces each query, key and value.
Article · free online · ~30 min
Transformer Inference Arithmetickipply · Sections “kv cache” and “flops counting”
Reproduce the cache size per token for a model you use, and explain why decoding is limited by memory rather than arithmetic.
Read the equation in context
Attention Is All You NeedAshish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser & Illia Polosukhin · NeurIPS, 2017Section 3.2.1 defines Equation (1) with queries, keys and values packed into matrices, so all outputs come from two matrix products. Read three passages around it: the footnote that justifies with the variance argument above; Section 3.2.2, where heads of dimensions replace one wide head; and Section 3.2.3, where the decoder prevents leftward information flow by setting the scores of illegal connections to inside the softmax. The paper's model is an encoder–decoder for translation. GPT-style models keep only the masked decoder stack, drop the cross-attention to an encoder, and train it with the factorisation from the opening glimpse.
Decode the paper · Section 3.2.1, Equation (1): scaled dot-product attention
Attention Is All You NeedAshish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N. Gomez, Łukasz Kaiser & Illia Polosukhin · NeurIPS, 2017
The paper packs many queries into one matrix and computes all attention outputs with two matrix products. Its footnote justifies the scaling: with independent unit-variance components, has variance . Section 3.2.3 adds the decoder's mask by setting illegal connections to inside the softmax.
Options
For the whole pipeline written and trained in code, from a bigram baseline to a small GPT with causal self-attention:
Your turn
Six toy tokens have fixed 2-D keys and values. Steer one query until a single token takes almost all the attention, then shorten or turn it until the attention spreads out, and watch the output stay inside the hull of the visible values. The panel underneath shows what goes wrong without the .
Interactive lab
Attention steerer
Query position
Each row shows the score q·k/√2 and its weight.
Top weight
54.4%
Temperature √d/‖q‖
1.41
Output o
(0.60, −0.07)
Visible tokens
6 of 6
Why divide by √d?
Draw a query and six keys with independent standard normal components in d dimensions, forty times. Raw dot products spread out like √d and the softmax saturates; dividing by √d keeps the spread near 1.
Spread of q·k (√d = 8)
8.66
Spread of q·k/√d
1.08
Mean top weight, raw
91%
Mean top weight, scaled
45%
Keys and values are illustrative; in a real head they are learned projections with d around 64 to 128. The lab uses d = 2.
Match · Expression ↔ Meaning
From logits to loss
Options
Match · Term ↔ Meaning
Attention and generation
Q @ K.T / np.sqrt(d_k)Options
Proof puzzle
Causal attention only blends the past
Claim
With causal mask , show that each output of is a convex combination of .
Tap lines in the order they should appear. Not every line belongs. Tap a line in your proof to send it back.
Your proof
- Pick the first line below.
Available lines
Prove it yourself
Shift invariance and the stable log-softmax
Claim
Prove that for every real . Deduce that, with , , and explain why this formula cannot overflow.
Your typeset proof appears here.
Coding problems
Problem 4·Warm-up
Perplexity from raw logits
A model with a four-token vocabulary (tokens 0 to 3) outputs logits at four positions. At position 1 the logits are and the true next token is 0; at position 2 they are and the token is 3; at position 3 they are and the token is 1; at position 4 they are and the token is 2.
Compute the model's perplexity on these four tokens, using natural logarithms, to 4 decimal places.
Problem 5·Standard
Causal attention at full size
Generate numbers with the Park–Miller generator , , and use for Fill an matrix row by row with , then with , then with .
Compute causal scaled dot-product attention with , where for and the softmax runs along each row. Give the sum of all 32 entries of to 6 decimal places.
Problem 6·Challenge
When the cache pays a hundredfold
Model a decoder with layers and width by its multiply–adds. Processing the token at position (counting from 1) costs, in each layer, for the weight matrices plus for attention over the visible positions. Ignore embeddings, norms and the softmax.
A prompt has tokens. Generating new tokens needs logits at positions . With a KV cache, every position from 1 to is processed exactly once. Without a cache, producing the -th new token () reprocesses all positions from scratch.
Find the smallest for which generation without the cache needs at least 100 times as many multiply–adds as generation with it.
Key takeaways
- A language model is a classifier over the vocabulary at every position; the chain rule turns its predictions into the probability of a whole text.
- Cross-entropy with teacher forcing trains every position in parallel. Perplexity, its exponential, is the effective number of choices, exactly for a uniform guesser.
- Causal scaled dot-product attention averages earlier values with softmax weights: the mask makes future weights exactly zero, keeps scores from saturating, and query length acts as an inverse temperature.
- A decoder-only transformer is embeddings, positional information, and residual blocks of attention and MLP, with about parameters in the blocks.
- Generation is prefill then decode. The KV cache reuses earlier keys and values, so each new token costs about FLOPs plus attention that grows with the context.
Checkpoint
Prove it to the labyrinth
Answer every question to clear this chamber. First-try answers earn the most XP.
Under teacher forcing, what does the model condition on when it predicts the token at position during training?
If the components of are independent with mean 0 and variance 1, what is the standard deviation of the unscaled score ?
Why is it valid to cache the keys and values of earlier positions while decoding?
You multiply a query vector by 3. What happens to that query's attention weights?
A model's validation loss is 1.5 nats per token. How many bits per token is that?
Two models report per-token perplexities of 9 and 12 on the same text, but they use different tokenisers. What can you conclude?
Estimate GPT-2 small's parameters in millions with , where , and .
Which statement about a causal attention output is always true?
For one position with logits and target , what is the gradient of with respect to ?
End of the chamber
Clear this chamber
- Questions in this chamber (0/14 solved)Next unsolved
- Bonus: Attention steerer (+30 XP)
- Bonus: Problem 4: Perplexity from raw logits (+20 XP)
- Bonus: Problem 5: Causal attention at full size (+35 XP)
- Bonus: Problem 6: When the cache pays a hundredfold (+50 XP)
- Bonus: Proof: Causal attention only blends the past (+25 XP)
- Bonus: Proof: Shift invariance and the stable log-softmax (+35 XP)
- Bonus: Decode the paper (+25 XP)
- Bonus: Match: From logits to loss (+20 XP)
- Bonus: Match: Attention and generation (+20 XP)