The idea
A transformer is a stack of identical blocks, each doing two things to a sequence of token vectors: mix across positions (multi-head attention), then process each position (a feed-forward network applied identically at every position). Everything else — residuals, layer norms, positional encodings — exists to make that stack trainable and order-aware. One pre-LN block:
Multi-head attention. Rather than one attention pattern over full-width vectors, split into heads of dimension :
Same total projection dimensions as one big head, but separately normalized attention patterns per token. Some trained heads exhibit interpretable positional or syntactic behavior, but specialization is not guaranteed and many heads can be redundant or pruned.
Position-wise FFN. with hidden width . It is where most parameters live, and it acts per token — attention is the only place information crosses positions.
Positional encodings. Attention is permutation-equivariant, so order must be injected. Sinusoidal encodings add a multi-wavelength sin/cos fingerprint of each position to its embedding:
Learned absolute embeddings (BERT) and rotary embeddings (most modern LLMs) are the common alternatives.
Why not RNNs? Three answers an interviewer wants, in order: (1) parallelism — RNN training is sequential in because needs ; a transformer trains on all positions at once as dense matrix algebra; (2) path length — relating tokens apart takes recurrent hops (gradients decay across each) versus exactly one attention hop; (3) scaling — transformers kept converting more data and compute into better loss. The price: attention versus recurrence, and inference memory (KV cache) versus an RNN's state.
Worked example
Parameter budget of one encoder block at , , FFN width 2048 (the original base config):
| Component | Count | Params |
|---|---|---|
| FFN in | ||
| FFN out | ||
| 2 LayerNorms | ||
| Total | M |
Read off the structure: two thirds of every block is FFN, attention projections are the other third, norms are noise. A 6-block stack is M parameters before embeddings; a 32k-token vocabulary at adds another M — for small models the embedding table rivals the whole stack, which is why input/output embeddings are often tied.
Sanity-check the multi-head shapes on a 10-token sentence: input → per head, are → scores per head (8 of them) → weighted values → concat → → . The sequence length only ever appears in the score matrices — that is the core in the flesh.
Cheat sheet
Block (pre-LN): , then ; FFN , width .
MHA: heads of ; params (Q, K, V, O); compute ≈ one full-width head; heads = independent attention patterns.
Positional encodings: sinusoidal (fixed, extrapolates in principle, relative offsets are linear maps); learned absolute (BERT); rotary/RoPE (relative, inside the QK product — modern default).
| RNN / LSTM | Transformer | |
|---|---|---|
| Training over length | sequential, steps | parallel, depth |
| Max dependency path | ||
| Compute per layer | ||
| Inference state | KV cache | |
| Long-range gradients | decay through gates | direct |
- Encoder-only blocks usually use bidirectional self-attention; decoder-only blocks use causal self-attention. Classical encoder-decoder transformers also add decoder cross-attention to encoder outputs, so the architectures differ by more than one mask.
- Pre-LN: stable deep training, mild warmup. Post-LN (original): needs warmup, unstable when deep.
- Parameter intuition: FFN ≈ 2/3 of block params; embeddings dominate small models.
- BERT-base for scale-anchoring: 12 layers, , 12 heads, ~110M params.
- Complexity gotcha: doubling context length quadruples attention compute but leaves parameter count unchanged.
- Attention is the only cross-token operation; FFN, LN, residuals are all per-token.