The transformer: the block, model families and vision transformers
Before this lesson: lesson 05 (LayerNorm, residual connections, pre-LN and post-LN), lesson 07 (strided convolutions), lesson 08 (tokens, embeddings, next-token prediction), lesson 09 (attention, masks, multi-head attention) and lesson 10 (positional encodings). Time: about 95 minutes, plus the notebook.
Why this matters #
Almost every large model of today is a transformer: GPT, LLaMA and most chat models (decoder-only), BERT (encoder-only), T5 and Whisper (encoder–decoder), and ViT, CLIP and the diffusion transformer DiT for images. The same block, with small changes, runs in AlphaFold-style protein models and in weather models such as ClimaX. If you know the block, its shapes and its costs, you can read most architecture papers, estimate how much memory and compute a model needs, and debug an implementation. Interviews ask exactly this: draw the block, count the parameters of GPT-2, estimate the training FLOPs of a 7B model, and explain the KV cache.
1. Predict first #
2. The picture #
Two kinds of mixing #
Write the tokens of a sequence as the rows of a matrix : tokens, each a vector of width . (As in the whole track, we use the row convention of PyTorch.) A network can combine numbers of this matrix in two directions:
- across tokens (down a column): token 3 uses information from token 7. Only attention does this, with weights that depend on the input (lesson 09).
- across features (along a row): the numbers of one token are combined into new numbers. The MLP (also called the feed-forward network, FFN) does this, with the same weights for every token.
A transformer block does both, one after the other. Around each of the two steps it puts a residual connection (the step's output is added to its input) and a LayerNorm (each token vector is normalized to mean 0 and variance 1, then scaled; lesson 05). The modern order, called pre-LN, is
Here is multi-head attention. The input , the middle value and the output all have the same shape . So blocks can be stacked: the output of one block is the input of the next. The sequence of vectors that flows through the stack, and that each block adds to, is called the residual stream.
Click a box (or tab to it and press Enter) to see its formula, its parameter count and its FLOPs. The blue arrows carry the residual stream; each label is the shape of the tensor on that arrow, for the batch size , length , width and heads you choose. Boxes with weights are violet; the selected box is yellow. Notice that every arrow between boxes has the same shape : only the inside of the attention ( weights per head) and of the MLP (width ) is different. Switch to post-LN to see where the LayerNorms move.
The whole model: text in, probabilities out #
A decoder-only language model such as GPT-2 is a stack of such blocks between an input part and an output part:
- Token embedding. Each token id selects one row of a learned matrix , where is the vocabulary size (lesson 08).
- Positions. Attention alone cannot see the order of the tokens (lesson 09), so position information is added. GPT-2 adds a learned vector for each position; LLaMA rotates the queries and keys instead (RoPE). Lesson 10 compares the methods.
- blocks, each with a causal mask: token attends only to tokens .
- A final LayerNorm, then the unembedding: a matrix product that maps each vector of width to logits, one score per possible next token.
- Softmax over the vocabulary gives the probabilities of the next token. Training minimizes the cross-entropy , summed over all positions at once.
Because of the causal mask, one forward pass over a text of tokens gives predictions in parallel: position predicts token from tokens only.
In a transformer block, which part lets the output vector of token 3 depend on the input vector of token 7?
The MLP, the LayerNorm and the residual connection all act on each token vector separately, with the same weights for every token. LayerNorm takes the mean over the features of one token, not over the tokens. Only attention mixes rows: row of is .
An image as a sequence of patches #
A transformer needs a sequence of vectors. An image is a grid of pixels. The vision transformer (ViT, Dosovitskiy et al., 2021) makes a sequence like this:
- Cut the image into non-overlapping squares of pixels, called patches. A image with gives a grid: patches.
- Read the patches row by row, like the words of a page. Patch of the grid becomes token number (counting from 0).
- Flatten each patch to one vector ( numbers for a color image) and map it with one shared linear layer to width .
- Put one extra learned token, [CLS], in front, and add a learned position vector to every token. Then run ordinary encoder blocks (no causal mask).
Choose the patch size and click a patch of the image. The right panel is the sequence the transformer sees: the violet [CLS] token first, then the patches in reading order. The yellow frame shows where your patch lands in the sequence. Notice how fast the token count grows when gets smaller: halving gives 4 times the tokens and about 16 times the size of each attention matrix. Switch to a image with the same : the patches stay the same size, but there are more of them.
A ViT gets a RGB image with patch size and a [CLS] token. How many tokens enter the first block, and how many numbers does each patch have before the linear map?
The grid is patches on each side, so patches, plus [CLS] gives 197 tokens. Each patch has pixels with 3 color channels: numbers. 256 forgets the channels; 14 is the side of the grid, not the number of patches.
3. Definitions and main results #
3.1 The transformer block #
Definition (MLP of a block). For a token matrix ,
with , , an activation (GELU in GPT-2, BERT and ViT; ReLU in the original transformer) and usually . LLaMA uses a SwiGLU MLP instead (lesson 04). The MLP acts on each row of separately.
Definition (transformer block). With multi-head attention (with or without a causal mask) and two LayerNorms with their own scale and shift vectors:
The original transformer (2017) and BERT use post-LN. GPT-2, LLaMA, ViT and most modern models use pre-LN. Lesson 05 explains the reason. In pre-LN, the direct path from to is the identity, so the gradient reaches early blocks at any depth. In post-LN, every LayerNorm sits on the main path, the gradients near the output are large at initialization, and training needs a learning-rate warmup.
What each part is for:
- Attention is the only part that moves information between tokens.
- The MLP is the computation on each token. It holds two thirds of the block's parameters (section 3.3). One common reading is that the MLPs store much of the model's knowledge, while attention routes information.
- Residual connections: each sublayer reads the residual stream and adds its result. A block can learn to change the stream only a little.
- LayerNorm keeps the input of each sublayer at a fixed scale. A pre-LN stack never normalizes the stream itself, so it needs a final LayerNorm after the last block.
Shapes through one pre-LN block (batch , heads of width ):
| Step | Shape |
|---|---|
| input , | |
| after the split into heads | |
| attention weights of all heads | |
| heads merged, after ; after the residual | |
| MLP hidden layer | |
| output |
3.2 The decoder-only language model #
Definition. Let the input be token ids . A decoder-only model with token embedding , learned position embedding and causal pre-LN blocks computes
with logits and the unembedding . Row of is , the predicted distribution of token . is the context length, the largest number of positions the model has embeddings for.
Weight tying. Many models set (Press and Wolf, 2017). Then the logit of token is the dot product of the final vector with the embedding of : tokens with similar embeddings get similar scores. Tying saves parameters; for GPT-2 small that is 38.6 million, about a third of the model. GPT-2 ties; LLaMA does not.
3.3 Counting parameters and FLOPs #
A FLOP is one floating-point operation. A multiply followed by an add counts as 2 FLOPs.
Theorem (parameters of one block). A block with width , , biases and two LayerNorms has parameters, for every number of heads.
Proof. Count each part.
- Multi-head attention: and four bias vectors of length : (lesson 09).
- MLP: has entries and has ; has and has : .
- Two LayerNorms, each with a scale and a shift of length : .
- Sum: , and .
For this is . The term is about 0.1%, so a block has about parameters: in attention and in the MLP.
Theorem (FLOPs of a linear layer). Let with (a batch of token vectors) and . Then
- the forward pass costs FLOPs: FLOPs per token per weight;
- the backward pass costs FLOPs: and each cost (lesson 03);
- so one training step costs FLOPs: 6 FLOPs per token per weight.
Proof. Each entry needs multiplications and additions, about FLOPs, and there are entries. The two backward products have the same three sizes , , in a different order, so each also costs .
Corollary (FLOPs per token of a transformer). Let be the number of weights that are multiplied for every token: in the blocks, plus for the unembedding (the embedding lookup reads one row and costs no FLOPs). For a context of tokens,
The term comes from attention: for one query, costs per head and another , so for all heads, in each of the blocks. (This counts all keys; a kernel that skips the masked half of a causal matrix does about half of it.) The rule "training costs about FLOPs per token" (Kaplan et al., 2020) holds when is small compared with , as we now show.
When does attention dominate? In one block, for one token, the weights cost FLOPs and the attention matrix costs . They are equal when , that is, at . For GPT-2 small () that is , far beyond its context of 1024: at attention is 18% of the per-layer FLOPs. For long contexts, the term wins.
Pick a preset, then move the sliders. The top bar splits the parameters, the bottom bar the forward FLOPs per token. In this figure the colors mark the parts of the model: embeddings and unembedding, attention weights, MLP, and the attention matrix, the only term that grows with the context . Notice that the MLP is always twice the attention weights. Then push past : the yellow part of the FLOPs bar becomes the largest.
A transformer block has , heads, , biases and two LayerNorms. About how many parameters does it have?
Attention has parameters, the MLP (two matrices of size ), and the LayerNorms . The heads split the width; they do not add parameters. counts only the attention. 85 million is the parameter count of 12 blocks (GPT-2 small without embeddings), not of 12 heads.
3.4 Three model families #
The same block makes three kinds of model. They differ in the masks and in what they are trained to do.
| Family | Self-attention mask | Cross-attention | Trained to | Examples |
|---|---|---|---|---|
| encoder-only | padding only: every token sees every token (bidirectional) | none | fill in masked tokens; classify | BERT, ViT |
| decoder-only | causal + padding | none | predict the next token | GPT, LLaMA |
| encoder–decoder | encoder: padding; decoder: causal | decoder queries, encoder keys and values | map an input sequence to an output sequence | original transformer, T5, Whisper |
- Encoder-only. BERT (Devlin et al., 2019) selects about 15% of the input tokens, hides most of them behind a [MASK] token, and learns to predict the original tokens from both sides. This is masked language modelling. The output vectors are good features for classification and search. An encoder cannot generate text left to right in a natural way, because every token sees the future.
- Decoder-only. GPT is trained on next-token prediction with teacher forcing (lesson 08): the input is the true text, the target is the same text shifted by one. It generates text by feeding its own output back in (section 3.5).
- Encoder–decoder. The encoder reads the whole input (a sentence to translate, an audio clip). The decoder writes the output. A decoder block has three sublayers: causal self-attention, cross-attention (queries from the decoder, keys and values from the final encoder output, lesson 09), and the MLP. So it has about parameters instead of . T5 (Raffel et al., 2020) is trained to fill in missing spans of text; the original transformer was trained to translate.
An encoder–decoder model translates a sentence. Which masks does the decoder use in its two attention sublayers?
Decoder self-attention must not see output tokens that are not written yet, so it is causal. Cross-attention reads the encoder output, and the whole input sentence is known before the decoder starts, so there is no future to hide: only padded input positions are masked. A causal mask on cross-attention would hide most of the source sentence for the first output tokens.
3.5 Generating text: decoding and the KV cache #
Autoregressive generation. Start with a prompt . Repeat: run the model, take the logits of the last position, choose a token , append it, and set . Stop at an end token or at a length limit.
Decoding rules (how to choose the token from ):
- Greedy: . Deterministic, but often repetitive.
- Temperature sampling: draw from
is the model's own distribution. makes it sharper; as it becomes greedy (when the largest logit is unique). makes it flatter; as it becomes uniform.
- Top- and top- (nucleus) sampling (Holtzman et al., 2020): set all probabilities to 0 except the largest, or except the smallest set of tokens whose probabilities sum to at least ; renormalize and sample. This removes the long tail of unlikely tokens.
The KV cache. Running the whole model on all tokens at every step repeats almost all the work. With a causal mask, it is not needed:
Theorem (cached keys and values do not change). In a decoder with causal self-attention, the hidden vector of token in every layer depends only on the tokens . So the keys and values of token , in every layer, do not change when later tokens are appended.
Proof (induction over the layers).
- Layer 0: row of is . It depends only on .
- Suppose that in layer , row depends only on , for every .
- In block , the LayerNorms, the MLP, the residual additions and the projections act on each row separately. The causal mask lets query read only the keys and values of rows , which by step 2 depend only on tokens with index .
- So row of layer depends only on . Its key and value are computed from it, so they do too.
So we store the keys and values of all past tokens in every layer: the KV cache. At each new step only the newest token goes through the model. Its query attends to the cached keys, and its new key and value are appended to the cache. The result is exactly the same as running the full model. For an encoder (no causal mask) the theorem fails: a new token changes the vectors of all earlier tokens, so nothing can be reused.
Work. Without a cache, step runs the dense layers on tokens, so generating tokens costs about token passes. With a cache, it costs token passes. The attention term still grows: the new query compares with cached keys.
Size of the KV cache. Each of the layers stores a key and a value of width for each of the tokens. So the cache of one sequence holds
(with standard multi-head attention, ). Multiply by the batch size and by the bytes per number (2 for fp16 or bf16). Multi-query attention (MQA; Shazeer, 2019) uses one key head and one value head shared by all query heads; grouped-query attention (GQA; Ainslie et al., 2023) uses groups. The cache is then numbers, times smaller.
Press Next token several times. A tiny hand-made model with one attention head writes a sentence. Each step adds one row to the cache of keys and values (the new row is yellow). The bars next to the cache are the attention weights of the newest token: it reads every cached row, but it computes only its own key and value. Below the cache: the probabilities of the next token at temperature . Set near 0 (greedy) or to 2, and compare the counters "with cache" and "without cache": the second grows like .
A decoder has layers, and standard multi-head attention. How large is its KV cache for one sequence of tokens in fp16 (2 bytes per number)?
numbers, times 2 bytes, is MB. 100 MB forgets one factor 2 (keys and values, or 2 bytes per number); 403 MB uses 4 bytes (fp32). The cache keeps the keys and values of all past tokens; that is its purpose.
3.6 The vision transformer #
Patch tokens. An image is cut into non-overlapping patches ( must divide both sides). Each patch is flattened to a vector of numbers and mapped by one shared matrix plus a bias : parameters.
Theorem (patch embedding is a strided convolution). Let a convolution have filters of size , stride and no padding, and let filter , flattened in the order (channel, row, column), be column of , with the same bias. Then output channel at grid position equals entry of .
Proof.
- A convolution computes, at each output position, the dot product of each filter with the input window at that position, plus the filter's bias (lesson 07).
- With kernel size and stride , the window of output position covers rows and columns . These windows do not overlap and they tile the image: window is exactly patch .
- The dot product of filter with the window equals the dot product of the two flattened vectors, if both are flattened in the same order. That is entry of . Adding the bias finishes the proof.
The output size formula of lesson 07 agrees: with , and ,
. Reading the
output grid row by row gives the token matrix. In PyTorch:
nn.Conv2d(C, D, kernel_size=P, stride=P), then .flatten(2).transpose(1, 2).
The model (Dosovitskiy et al., 2021). With a learned class token and learned position embeddings :
then pre-LN encoder blocks (no causal mask) and a final LayerNorm. The final vector of the [CLS] token is the representation of the image; a linear layer on it gives the class logits. (Many later models take the mean of the patch vectors instead of a [CLS] token.) The position embeddings are 1-D: one learned vector per index in reading order. In the ablation of the ViT paper, 2-D and relative position embeddings were not better, but no position embedding at all was clearly worse.
Counting. tokens. Parameters: patch embedding , class token , position embeddings , about per block, and the head. ViT-B/16 (, , , , images) has 86.6 million parameters with a 1000-class head (section 4). The attention matrices cost and , so halving gives about 16 times the attention cost.
Inductive bias and data. An inductive bias is an assumption that is built into the architecture. A CNN assumes locality (a pixel interacts first with its neighbors) and translation equivariance in every layer (lesson 07). A ViT assumes much less: only the cut into patches and the per-token MLPs are local; self-attention connects every patch with every other patch from the first layer; the learned position embeddings start with no 2-D structure. The ViT must learn these structures from data. So:
- trained on ImageNet-1k alone (1.3 million images) with the usual regularization, a ViT ends a few points below a ResNet of similar size;
- pre-trained on ImageNet-21k (14 million images) or JFT-300M (300 million), it matches or beats the best CNNs;
- DeiT (Touvron et al., 2021) trains ViTs well on ImageNet-1k alone, with strong data augmentation (RandAugment, Mixup, CutMix, random erasing), stochastic depth, label smoothing and AdamW (lesson 06). DeiT-B (86 million parameters) reaches 81.8% top-1 accuracy at .
After training, nearby patches have similar position embeddings: the model has learned the 2-D layout.
A new resolution. To fine-tune at a higher resolution, keep (the patch-embedding weights fix it). Then grows, and the position embeddings no longer fit. Reshape the patch rows of into their 2-D grid, resize the grid by 2-D interpolation (DeiT uses bicubic), flatten it again, and keep the [CLS] row unchanged. The block weights need no change: they work for any number of tokens.
Why the blocks accept any number of tokens
Every weight matrix in a block acts along the feature axis: have shapes or , never . Attention forms a matrix from the data, not from a parameter. So the same weights apply to 197 or 577 tokens. Only the position embeddings (a parameter) and the causal mask (a pattern) depend on . This is also why a decoder with learned absolute positions cannot read beyond : it has no embedding for those positions, while the blocks themselves would run (lesson 10).
Answers to section 1. (1) The MLP. It has parameters and the attention : about twice as many, for every number of heads. (2) Step processes tokens, so the total is token passes: quadratic in . With a causal mask, the keys and values of past tokens never change (theorem of section 3.5), so the model stores them in a KV cache, and each step processes only the new token. (3) The patch size stays 16 and the block weights stay the same. The number of tokens grows from to (plus [CLS]). The position embeddings must be resized from a grid to a grid by interpolation.
4. Worked example #
(a) One pre-LN block by hand #
Take tokens of width , one head (), LayerNorm scale 1 and shift 0 (and we ignore its small ), no biases, , an MLP with , , ReLU and . (ReLU keeps the numbers simple; GPT-2 uses GELU.) The input is
Step 1, LayerNorm of each row. Row 1: mean , variance , so . Row 2: mean , variance , standard deviation , so . (With , a LayerNorm can only output ; real models have in the hundreds or thousands.)
Step 2, attention. , and . The scores are
Row 1: and , sum , weights . Row 2 is the mirror image: . Row 1 of the output is , and row 2 is its mirror image:
With this is the attention output.
Step 3, first residual. .
Step 4, LayerNorm of . Row 1 has mean and the deviations , so it becomes . Row 2 has mean and the deviations , so it becomes .
Step 5, MLP. Row 1: , times gives . Row 2: , then .
Step 6, second residual. Add the MLP output to , row by row: and .
With a causal mask, token 1 sees only itself: its weights are , its attention output is , , the MLP adds , and . Token 2 sees both tokens and does not change: .
(b) GPT-2 small: parameters and FLOPs #
GPT-2 small has , context , , , , tied weights.
| Part | Count | Parameters |
|---|---|---|
| token embedding (= unembedding) | ||
| position embedding | ||
| 12 blocks | ||
| final LayerNorm | ||
| total |
FLOPs per token: the weights multiplied per token are million. Forward: MFLOP, plus attention MFLOP at : about 285 MFLOP per token. Training: about MFLOP per token. On 10 billion training tokens that is about FLOPs.
(c) Generation: temperature and the KV cache #
The model gives the logits for three candidate tokens.
- : , sum , so .
- : , , sum , so .
- : , , sum , so .
- : greedy, always token 1.
KV cache of GPT-2 small for one sequence of tokens in fp16: numbers, times 2 bytes MB. The weights in fp16 take MB. At a batch of 32 sequences the cache needs about 1.2 GB, five times the weights.
A larger model with grouped-query attention: LLaMA-2 70B has , query heads of width and key-value heads. At in fp16: bytes GB per sequence. With 64 key-value heads it would be 8 times as much, about 10.7 GB.
(d) ViT-B/16 #
, images, , , , 1000 classes.
| Part | Count | Parameters |
|---|---|---|
| patch embedding | ||
| class token | ||
| position embeddings | ||
| 12 blocks | ||
| final LayerNorm | ||
| head | ||
| total |
Fine-tuning at . Keep . The grid becomes patches, 577 tokens. Resize the grid of position embeddings to and keep the [CLS] row. The per-token costs grow by , and the attention matrices by .
5. In code #
PyTorch checks the worked examples. The notebook builds the block, a tiny GPT with a KV cache and the patch embedding yourself.
import torch
import torch.nn as nn
import torch.nn.functional as F
torch.manual_seed(0)
# (a) the tiny pre-LN block of the worked example
blk = nn.TransformerEncoderLayer(d_model=2, nhead=1, dim_feedforward=2,
dropout=0.0, activation="relu", bias=False,
batch_first=True, norm_first=True)
with torch.no_grad():
blk.self_attn.in_proj_weight.copy_(torch.eye(2).repeat(3, 1)) # W_Q=W_K=W_V=I
blk.self_attn.out_proj.weight.copy_(torch.eye(2)) # W_O = I
blk.linear1.weight.copy_(torch.eye(2)) # W_1 = I
blk.linear2.weight.copy_(0.5 * torch.eye(2)) # W_2 = I/2
X = torch.tensor([[[2., 0.], [0., 1.]]])
print(blk(X).detach().numpy().round(3))
# [[[ 3.388 -0.888]
# [-0.888 2.388]]]
causal = nn.Transformer.generate_square_subsequent_mask(2)
print(blk(X, src_mask=causal).detach().numpy().round(3))
# [[[ 3.5 -1. ]
# [-0.888 2.388]]]
# (b) 12 D^2 + 13 D parameters per block, and GPT-2 small
layer = nn.TransformerEncoderLayer(768, 12, 3072, batch_first=True, norm_first=True)
print(sum(p.numel() for p in layer.parameters()), 12 * 768**2 + 13 * 768)
# 7087872 7087872
V, Tmax, D, L = 50257, 1024, 768, 12
print(V * D + Tmax * D + L * (12 * D**2 + 13 * D) + 2 * D)
# 124439808
# (c) temperature and the KV cache
z = torch.tensor([2., 1., 0.])
for tau in (1.0, 0.5, 2.0):
print(tau, torch.softmax(z / tau, -1).numpy().round(3))
# 1.0 [0.665 0.245 0.09 ]
# 0.5 [0.867 0.117 0.016]
# 2.0 [0.506 0.307 0.186]
print(2 * L * Tmax * D * 2 / 1e6, "MB") # 37.748736 MB
# (d) ViT-B/16: the patch embedding is a convolution with kernel = stride = 16
conv = nn.Conv2d(3, 768, kernel_size=16, stride=16)
x = torch.randn(1, 3, 224, 224)
tokens = conv(x).flatten(2).transpose(1, 2) # (1, 196, 768)
patches = x.reshape(3, 14, 16, 14, 16).permute(1, 3, 0, 2, 4).reshape(196, 768)
by_hand = patches @ conv.weight.reshape(768, -1).T + conv.bias
print(tokens.shape, torch.allclose(tokens[0], by_hand, atol=1e-5))
# torch.Size([1, 196, 768]) True
pos = torch.randn(1, 197, 768) # [CLS] row + 14 x 14 grid
grid = pos[:, 1:].reshape(1, 14, 14, 768).permute(0, 3, 1, 2)
grid = F.interpolate(grid, size=(24, 24), mode="bicubic", align_corners=False)
grid = grid.permute(0, 2, 3, 1).reshape(1, 576, 768)
new_pos = torch.cat([pos[:, :1], grid], dim=1) # keep the [CLS] row
print(new_pos.shape)
# torch.Size([1, 577, 768])
The bias=False option (PyTorch 2.1 or later) removes the biases of the linear layers and the
shifts of the LayerNorms. The inside LayerNorm changes the result only after
the third decimal.
6. Where it shows up #
- Large language models. GPT-2, GPT-3, LLaMA, Mistral and most chat models are decoder-only stacks. LLaMA changes three parts of the GPT-2 block: RMSNorm instead of LayerNorm (lesson 05), a SwiGLU MLP (lesson 04) and RoPE instead of learned positions (lesson 10). The plan of this lesson (embedding, pre-norm blocks, final norm, unembedding) stays the same.
- Serving models. Inference has two phases. In prefill the model reads the prompt in one parallel pass and fills the KV cache. In decode it makes one token per step; each step reads all weights and the whole cache from memory, so speed is limited by memory bandwidth, not by FLOPs. GQA, cache quantization and paged cache memory (as in vLLM) all make the cache cheaper.
- Compute budgets. The rule "6 FLOPs per parameter per training token" gives quick estimates: a 7-billion-parameter model trained on 2 trillion tokens needs about FLOPs. Scaling laws are written in these units.
- Encoders. BERT-style encoders produce text embeddings for search and classification. Encoder–decoders run speech recognition (Whisper: an audio encoder and a text decoder) and translation.
- Vision. ViTs are the image encoders of most CLIP models, of DINO (lesson 14) and of the Segment Anything model. The diffusion transformer (DiT) applies the same patch tokens to the latent images of a diffusion model. Swin transformers restrict attention to local windows, which brings back a CNN-like locality bias and a cost linear in the number of patches.
- Science. ClimaX is a ViT-style weather and climate model that makes patch tokens for each
physical variable separately and then merges them per patch. Pangu-Weather uses a 3-D
transformer over latitude, longitude and pressure levels. Seismic and other time series are cut
into 1-D patches (a strided
Conv1d), as in PatchTST for forecasting.
7. Common mistakes #
- No final LayerNorm in a pre-LN stack. The residual stream is never normalized inside the blocks; without the final norm its scale grows with depth and reaches the logits.
- "Attention is the expensive part." At short and medium lengths, the MLP and the projections dominate: attention matrices cost more only when .
- FLOP counts off by 2 or 3. A multiply-add is 2 FLOPs; a training step is about 3 times the forward pass (the backward pass computes two products per linear layer).
- A wrong position for the new token in cached generation. The new token at step must get position (its learned embedding or its RoPE angle), not position 1. Without a cache this bug cannot happen, so test cached against uncached generation.
- A KV cache for an encoder. Without a causal mask, a new token changes the keys and values of all earlier tokens, so a cache gives wrong results.
- Temperature 0 as a division. with gives infinities and NaN. Implement as greedy decoding.
- Changing the patch size for a new resolution. Keep , let grow, interpolate the position grid. Do not interpolate the [CLS] row, and do not forget it in the token count ().
- A patch flattening order that does not match the convolution weights. A filter of
nn.Conv2dis flattened in the order (channel, row, column); your patches must use the same order. - "A ViT has no inductive bias." It has less image-specific bias than a CNN, not none: the patches, the per-token MLPs and the permutation symmetry of attention are all built-in choices.
8. Check yourself #
- A pre-LN block has , , , and . Give the shapes of
, of the queries after the split into heads, of the attention weights, of
the MLP hidden layer and of the block output.
Answer
. : . Queries: . Attention weights: . MLP hidden layer: . Output: , the same as the input. - A decoder-only model has , learned positions, ,
, , biases and a final LayerNorm. Count its parameters with tied weights, and
without tying.
Answer
Embedding ; positions ; blocks ; final LayerNorm . Tied: . Untied: add for (no bias in GPT-style models), . Here the embeddings are about 40% of the tied model. - Why can a decoder reuse the keys and values of earlier tokens when it appends a token, while BERT
cannot?
Answer
With a causal mask, the vector of token in every layer depends only on tokens (proof by induction over the layers), so its key and value never change. In BERT every token attends to every token, so a new token changes the vectors, keys and values of all earlier tokens in every layer after the first. - A ViT for CIFAR-10 images () uses , and a [CLS] token.
Count the tokens, the patch-embedding parameters (with bias) and the position-embedding parameters.
Answer
patches, 65 tokens. Patch embedding: . Position embeddings: . - At you halve the patch size from 16 to 8. By which factors do the number of tokens
and the size of each attention matrix grow?
Answer
Patches: , a factor 4 (197 to 785 tokens with [CLS]). The attention matrix has entries: a factor of about 16 (). - A model has . From which context length on does the attention matrix cost more
FLOPs per token than all the weights of a block?
Answer
Per token and per block, the weights cost FLOPs and the attention matrix . So .
Write the two equations of a pre-LN transformer block.
and .
Which part of a transformer block mixes information between tokens?
Only the attention. The MLP, LayerNorm and residual connections act on each token separately.
How many parameters does a transformer block with width and have, and how are they split?
About (exactly with biases and LayerNorms): in attention and in the MLP.
Why does training cost about 6 FLOPs per parameter per token?
The forward pass costs 2 (one multiply-add per weight); the backward pass computes two products of the same size, the gradients for the inputs and for the weights, which costs 4 more.
At which context length does the attention matrix cost as much as the weights of a block?
At : per token, the weights cost FLOPs and the attention matrix .
What masks do encoder-only, decoder-only and encoder–decoder models use?
Encoder: padding only (bidirectional). Decoder: causal plus padding. Encoder–decoder: padding in the encoder, causal self-attention plus cross-attention (no causal mask) in the decoder.
Why does a KV cache give exactly the same output as running the full model again?
With a causal mask, the vector of token in every layer depends only on tokens , so its keys and values never change when tokens are appended.
How many numbers does the KV cache of one sequence hold?
with standard multi-head attention ( layers, tokens, width ); with grouped-query attention.
How many tokens does a ViT make from a image with and a [CLS] token?
.
How do you fine-tune a ViT at a higher resolution?
Keep the patch size ; reshape the patch rows of the position embeddings to their 2-D grid, interpolate it to the new grid size (bicubic), and keep the [CLS] row.
9. Interview angle #
- "Draw a transformer block and give all shapes." — Pre-LN: LN, multi-head attention, add; LN, MLP (), add. Every arrow is ; inside attention and . Name the final LayerNorm.
- "How many parameters does GPT-2 small have?" — per block gives M for 12 blocks; the token embedding adds M and positions M; tied unembedding; total M.
- "How many FLOPs to train a 7B model on 2T tokens?" — parameters tokens , plus the attention term if the context is long.
- "What is the KV cache, how big is it, and how do you make it smaller?" — Stored keys and values of past tokens, exact because of the causal mask; numbers per sequence; shrink it with MQA/GQA, a lower-precision cache, or a sliding window.
- "BERT, GPT, T5: what is the difference?" — Masks (bidirectional, causal, both), training task (masked tokens, next token, span infilling), cross-attention in the decoder of T5.
- "How does a ViT work, and why does it need more data than a CNN?" — Patches as tokens (a strided convolution), [CLS] and learned positions, a standard encoder. It has fewer built-in assumptions about images, so it learns them from data; DeiT compensates with augmentation and regularization.
10. Practice #
The notebook for this lesson runs in Colab (PyTorch on a CPU, under a minute). It has five exercises, each with a check cell and a folded solution:
- Write a pre-LN transformer block from tensor operations and match PyTorch's
nn.TransformerEncoderLayer(withnorm_first=True) with copied weights. - Write a function that counts the parameters of a GPT-style model and check it against
sum(p.numel() for p in model.parameters())and GPT-2 small. - Write temperature sampling (with as greedy) and use it on a tiny character-level GPT that the notebook trains on a short text in a few seconds.
- Add a KV cache to the tiny GPT and check that cached and uncached generation give the same tokens.
- Write the ViT patch embedding as a reshape and a matrix product, and check it against
nn.Conv2d(kernel_size=P, stride=P).
11. Watch and read #
- Vaswani et al., Attention Is All You Need (2017): §3 (the encoder–decoder architecture, the FFN) and Table 3 (model sizes).
- Prince, Understanding Deep Learning, free PDF: chapter 12 (§12.4 transformer layers, §12.6–12.8 encoders, decoders, encoder–decoders, §12.10 transformers for images).
- Rush et al., The Annotated Transformer: the whole model in commented PyTorch code.
- Kaplan et al., Scaling Laws for Neural Language Models (2020): §2.1, Table 1 (parameters and FLOPs per token of a transformer).
- Kipply, Transformer Inference Arithmetic: KV cache size, FLOPs, and why decoding is limited by memory bandwidth.
- Dosovitskiy et al., An Image is Worth 16x16 Words (ViT, 2021): §3.1–3.2 (model, inductive bias, higher resolution), §4.3 (data size), Appendix D.4 (position embeddings).
- Touvron et al., Training data-efficient image transformers (DeiT, 2021): §4–6 (distillation token, training recipe).
- Devlin et al., BERT (2019) and Raffel et al., T5 (2020): the training tasks of the encoder-only and encoder–decoder families.
- Ainslie et al., GQA (2023): grouped-query attention, and how to convert a multi-head model to it.
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.