Interpretable
Module 1.1 · ~2h

Tokens & Embeddings

How text becomes vectors: BPE, tokenizer pathologies, and the geometry of embedding space.

You'll be able to
  • Run BPE merges by hand and explain why tokenizers exist
  • Diagnose real LLM failures caused by tokenization
  • Describe embedding space geometry and tied unembeddings
Learn

The model never sees your text

Before a transformer does anything, a completely separate program chops your string into pieces and looks each piece up in a table. That program is the tokenizer, the pieces are tokens, and the model only ever sees the results. It has no access to the original characters. Almost every surprising low-level failure in this course traces back to that sentence.

text“the cat”tokensthe | ·catids1169 | 3797vectors768 numbers ×2tokenizer (no learned weights)embedding matrix W_Eone forward pass starts here
The full front end of a language model. Only the last arrow involves learned model weights; everything before it is a lookup table built by a program that was trained separately, on a different objective.

Why not feed the model characters? You could, and some models do, but an average English word is 4–5 characters, so every sentence becomes 4–5× longer. Attention cost grows with the square of sequence length, so character models spend their compute re-deriving spelling instead of meaning.

Why not whole words? Then the vocabulary is unbounded (every typo, every name, every URL is a new word), rare words get almost no training signal, and anything unseen becomes an <UNK> hole in the input.

Key idea
Subword tokenization is the compromise that won: frequent words get one token, rare words get split into pieces, and nothing is ever unrepresentable. GPT-2 uses 50,257 tokens; GPT-4o's tokenizer uses roughly 200,000. Bigger vocabulary means fewer tokens per sentence (cheaper, longer effective context) but a larger embedding matrix and a harder final softmax.
token
The atomic unit of input and output. Not a word, not a character, not a morpheme — just a frequent byte string that the tokenizer decided deserves an entry in the table. The leading space usually belongs to the token: ·cat and cat are two different entries with two different vectors.
Learn

BPE: build a vocabulary by merging

Byte-pair encoding learns the vocabulary from data with an almost embarrassingly simple loop. Start with every character as its own symbol. Count every adjacent pair of symbols in the corpus. Merge the most frequent pair into one new symbol. Repeat until you have as many merges as you wanted.

startl o w · l o w e r · n e w e s t · w i d e s tmerge 1l o w · l o w e r · n e w es t · w i d es te + s → es (9×)merge 2l o w · l o w e r · n e w est · w i d estes + t → est (9×)merge 3lo w · lo w e r · n e w est · w i d estl + o → lo (7×)merge 4low · low e r · n e w est · w i d estlo + w → low (7×)
Four BPE merges on the classic toy corpus: low ×5, lower ×2, newest ×6, widest ×3. Each row merges the most frequent adjacent pair (ties broken by first appearance). The merges are remembered in order — that ordered list is the entire tokenizer.

The payoff shows up on words the corpus never contained. Feed lowest to the four merges above, in order, and you get low + est — two learned pieces, no <UNK>, and a segmentation that happens to be morphologically sensible. That is the whole trick: frequent things get short, rare things get decomposed.

Key idea
Encoding is not longest-match or dictionary lookup. It replays the learned merges in the order they were learned. Rank 0 fires everywhere it can, then rank 1, and so on. Two tokenizers with identical vocabularies but different merge orders segment text differently — the order is part of the model.

Real implementations add two wrinkles. First, a pre-tokenization regex splits text into words, numbers, and punctuation runs before any merging, so merges can never straddle a space or glue a word to a comma. Second, byte-level fallback: GPT-2 works on the 256 raw bytes rather than Unicode characters, so any input at all — emoji, Klingon, binary — is encodable, just expensively. The widget below has the first wrinkle and not the second; characters missing from its small corpus get flagged instead.

The tokenizer is trained before the model, and separately
BPE training optimises compression on a tokenizer corpus. It knows nothing about the language model, its data, or its loss. Whatever it decides, the model is stuck with for its entire life — and, as the next section shows, so are you.
Learn

Where tokenizers bite

A tokenizer is a lossy interface between the world and the model. Four failure families come straight out of that interface, and you can predict all four from the mechanism.

1. Arithmetic. A model can only learn a clean addition algorithm if digits arrive in consistent chunks. GPT-2 and GPT-3 gave hundreds of multi-digit numbers their own tokens with no consistent grouping, so 380 + 42 and 381 + 42 can have completely different token shapes. Beren Millidge's Integer tokenization is insane walks through how bad it was; his 2024 follow-up notes that newer tokenizers adopted consistent digit grouping, which is one reason arithmetic improved without anything changing in the architecture.

2. Spelling and counting letters. Asking how many rs are in strawberry asks the model to report on characters it never received. It can often answer anyway — spelling is recoverable from context and from the token string itself — but it is doing inference, not lookup, and it fails in the way that inference fails. Tokenization is not the whole story here, but it is why the task is hard at all.

3. Glitch tokens. In 2023 Jessica Rumbelow and Matthew Watkins found tokens like  SolidGoldMagikarp sitting near the centre of GPT-2's embedding cloud. These strings were frequent in the tokenizer's training data (Reddit usernames from counting threads) but essentially absent from the model's training data, so their embedding vectors were never trained away from their random initialisation. Prompting with them produced evasion, insults, hallucinated completions, and broke determinism at temperature 0. Land & Bartolo later automated detection of such under-trained tokens across many production models — they are not a historical curiosity.

4. Language inequity. Petrov et al. measured tokenized length for the same text across languages and found differences of up to 15×. Since APIs bill per token and context windows are counted in tokens, speakers of under-represented languages pay more money for less context and slower responses — a fairness problem baked in before inference starts.

Safety tie-in
Two safety consequences worth carrying forward. First, glitch tokens are an attack surface: inputs that put a model far off the distribution its safety training covered, reachable by anyone who can type. Any evaluation of a safety property is an evaluation over the token distribution you tested, and rare-token space is enormous. Second, tokenization silently distorts measurement: a capability eval that looks like a reasoning benchmark can be partly a tokenization benchmark, so “the model cannot do X” sometimes means “the model cannot see X.” Before blaming cognition, check the tokens.
The trailing-space trap
Because the leading space belongs to the following token, “The capital of France is” and “The capital of France is ” are genuinely different inputs. The second one has already committed to a token boundary the training data almost never contains, and quality drops. If a prompt behaves strangely, look at its last character first.
Learn

From ids to geometry

A token id is just a row number. The embedding matrix WERnvocab×dmodelW_E \in \mathbb{R}^{n_{\text{vocab}} \times d_{\text{model}}} holds one learned vector per token, and “embedding a token” means taking that row:

xt=WETet(one-hot et selects row t)x_t = W_E^{\mathsf{T}} \, e_{t} \quad\text{(one-hot } e_t \text{ selects row } t)

Written as a matrix product it looks like computation; it is a table lookup. For GPT-2 small, 50,257×76838.650{,}257 \times 768 \approx 38.6 million parameters — roughly 31% of the model's 124M, spent before any thinking happens.

Key idea
The embedding vector is the starting value of the residual stream at that position, not the model's understanding of the token. Every later layer reads that stream and adds to it. By the middle layers the vector at a position encodes far more about context than about the token that seeded it — the first layers of a transformer are substantially in the business of undoing the tokenizer.

Because tokens with similar contexts get similar gradient pressure, embedding space acquires structure: numbers cluster with numbers, punctuation with punctuation, code keywords with code keywords. The famous stronger claim is analogy arithmetic kingman+womanqueen\text{king} - \text{man} + \text{woman} \approx \text{queen} — which says related pairs are separated by a consistent offset vector, not just placed nearby.

How much to believe about analogies
The clusters are robust and easy to verify yourself. The clean analogy arithmetic is weaker than its fame suggests: results depend on excluding the query words from the answer candidates, work far better for some relation types (gender, capitals) than others, and are noisier in modern subword embeddings than in the word2vec-era results that made them famous. Treat “consistent offsets exist” as a real but partial phenomenon — the map below shows the idealised version so you know what the claim means.

At the other end of the model, the unembedding WUW_U turns the final residual vector back into 50,257 logits — and each logit is a dot product between the residual stream and one row, exactly the similarity operation from Module 0.1:

logitt=xfinalWU[:,t]\text{logit}_t = x_{\text{final}} \cdot W_U[:, t]
tied embeddings
Many models, GPT-2 included, use the same matrix for input and output: WU=WETW_U = W_E^{\mathsf{T}}. It saves ~38M parameters and, per Press & Wolf, improves perplexity. It also means one geometry serves two jobs — the direction that reads in a token is the direction that writes out that token, which is why you can measure “how much is the model pushing toward token tt” by projecting onto an embedding row.

That last observation is the whole idea behind the logit lens: if the unembedding can decode the final residual stream, point it at an intermediate layer and watch the prediction form. Module 3.1 does this properly. For now, notice that it is only possible because input and output live in the same vector space.

Explore

Play: tokenize and map

The first widget trains a genuine BPE tokenizer in your browser — 200 merges over a small corpus, learned when the page loads — and re-segments whatever you type on every keystroke. The second is a hand-built picture of embedding-space structure, which is honest about being a diagram rather than a projection of real weights.

BPE tokenizer, trained live
Two hundred merges, learned right now from a small built-in corpus about this course. Type anything; the segmentation updates on every keystroke. The middle dot is a space — it belongs to the token that follows it.
sample text
segmentation — click a token to trace how it was built
merge trace for The
  1. rank 1T|h|e
  2. rank 69T|he
  3. finalThe
learned merges (in the order they were learned)
  • 0· + t·t×117
  • 1h + ehe×71
  • 2· + a·a×68
  • 3·t + he·the×56
  • 4e + nen×55
  • 5e + rer×54
  • 6i + nin×51
  • 7· + s·s×44
  • 8o + ror×42
  • 9· + m·m×38
  • 10o + kok×36
  • 11ok + enoken×35
  • 12· + o·o×35
  • 13a + rar×34
  • 14o + dod×31
  • 15· + i·i×31
  • 16·t + oken·token×31
  • 17e + lel×29
  • 18·a + n·an×29
  • 19a + tat×28
  • 20·an + d·and×27
  • 21e + ses×26
  • 22n + ene×24
  • 23od + elodel×23
  • 24· + b·b×23
  • 25r + ere×22
  • 26· + w·w×22
  • 27· + c·c×22
  • 28in + ging×22
  • 29· + l·l×20
  • 30·m + odel·model×20
  • 31e + cec×20
  • 32· + ···×20
  • 33·i + s·is×19
  • 34or + dord×18
  • 35·o + f·of×18
  • 36· + p·p×18
  • 37a + nan×17
  • 38i + tit×17
  • 39a + cac×17
  • 40· + d·d×15
  • 41v + erver×14
  • 42o + non×14
  • 43o + mom×14
  • 44·s + t·st×13
  • 45· + v·v×13
  • 46· + e·e×13
  • 47· + f·f×13
  • 48· + in·in×13
  • 49·i + t·it×12
  • 50·w + ord·word×12
  • 51o + tot×11
  • 52i + ziz×11
  • 53s + tst×11
  • 54s + ese×11
  • 55a + lal×11
  • 56a + inain×11
  • 57g + ege×10
  • 58·l + e·le×10
  • 59· + u·u×10
  • 60·token + iz·tokeniz×10
  • 61· + ne·ne×10
  • 62·s + p·sp×10
  • 63·t + r·tr×10
  • 64m + bmb×10
  • 65x + txt×9
  • 66·t + h·th×9
  • 67·tokeniz + er·tokenizer×9
  • 68e + ded×9
  • 69T + heThe×9
  • 70· + re·re×8
  • 71a + dad×8
  • 72er + sers×8
  • 73·th + at·that×8
  • 74·o + ne·one×8
  • 75 + ⏎⏎×8
  • 76u + lul×8
  • 77·b + ec·bec×8
  • 78·tr + ain·train×8
  • 79en + tent×8
  • 80ec + tect×8
  • 81l + yly×8
  • 82u + cuc×8
  • 83·· + ······×8
  • 84· + n·n×7
  • 85·token + s·tokens×7
  • 86u + nun×7
  • 87e + xtext×7
  • 88a + sas×7
  • 89o + coc×7
  • 90·o + n·on×7
  • 91·e + ver·ever×7
  • 92i + onion×7
  • 93·v + ect·vect×7
  • 94·vect + or·vector×7
  • 95·word + s·words×6
  • 96·c + h·ch×6
  • 97·p + r·pr×6
  • 98t + sts×6
  • 99· + h·h×6
  • 100·v + oc·voc×6
  • 101·voc + a·voca×6
  • 102·voca + b·vocab×6
  • 103·vocab + ul·vocabul×6
  • 104·vocabul + ar·vocabular×6
  • 105·vocabular + y·vocabulary×6
  • 106·ever + y·every×6
  • 107ac + eace×6
  • 108·b + e·be×6
  • 109·train + ing·training×6
  • 110it + hith×6
  • 111·m + er·mer×6
  • 112f + orfor×6
  • 113·n + ot·not×5
  • 114t + ersters×5
  • 115· + A·A×5
  • 116u + tut×5
  • 117en + cenc×5
  • 118·sp + ace·space×5
  • 119· + r·r×5
  • 120at + ionation×5
  • 121·bec + om·becom×5
  • 122a + iai×5
  • 123·mer + g·merg×5
  • 124·merg + es·merges×5
  • 125·le + ar·lear×5
  • 126d + ingding×5
  • 127· + The·The×5
  • 128·st + r·str×5
  • 129t + utu×5
  • 130i + mim×5
  • 131·d + o·do×4
  • 132·re + ad·read×4
  • 133·t + ext·text×4
  • 134o + pop×4
  • 135·h + as·has×4
  • 136e + pep×4
  • 137·s + it·sit×4
  • 138·f + r·fr×4
  • 139·fr + om·from×4
  • 140·d + at·dat×4
  • 141·dat + a·data×4
  • 142·w + ith·with×4
  • 143·c + o·co×4
  • 144ac + hach×4
  • 145m + eme×4
  • 146ne + dned×4
  • 147·m + at·mat×4
  • 148·f + or·for×4
  • 149mb + edmbed×4
  • 150mbed + dingmbedding×4
  • 151·ne + ar·near×4
  • 152an + geange×4
  • 153 + ····⏎····×4
  • 154·do + es·does×3
  • 155·ch + un·chun×3
  • 156·chun + k·chunk×3
  • 157t + hethe×3
  • 158·st + ar·star×3
  • 159·u + se·use×3
  • 160ar + acarac×3
  • 161m + odelmodel×3
  • 162en + dend×3
  • 163·st + ep·step×3
  • 164·s + e·se×3
  • 165·c + an·can×3
  • 166w + ordword×3
  • 167·bec + a·beca×3
  • 168·beca + u·becau×3
  • 169·becau + se·because×3
  • 170·a + l·al×3
  • 171a + yay×3
  • 172ac + kack×3
  • 173·p + ai·pai×3
  • 174·pai + r·pair×3
  • 175enc + odencod×3
  • 176encod + ingencoding×3
  • 177i + lil×3
  • 178o + lol×3
  • 179p + epe×3
  • 180· + ord·ord×3
  • 181·ord + er·order×3
  • 182·lear + ned·learned×3
  • 183·a + p·ap×3
  • 184p + lpl×3
  • 185·s + a·sa×3
  • 186for + efore×3
  • 187·d + i·di×3
  • 188·di + f·dif×3
  • 189·dif + f·diff×3
  • 190·diff + er·differ×3
  • 191·differ + ent·different×3
  • 192·e + ach·each×3
  • 193·becom + es·becomes×3
  • 194·mat + r·matr×3
  • 195·matr + i·matri×3
  • 196·matri + x·matrix×3
  • 197·l + o·lo×3
  • 198·u + p·up×3
  • 199p + rpr×3

Highlighted merges are the ones that fired on your text. The count is how often the pair appeared in the corpus when it was merged — notice how fast it falls, and imagine that curve continuing to merge 50,000.

122 characters → 54 tokens (2.26 characters per token). Vocabulary at this setting: 253 (53 characters + 200 merges). 1 token came from characters the corpus never contained — dashed outline. A real tokenizer avoids this by falling back to raw bytes, which is why GPT-2 can encode any input at all, just expensively.
Embedding-space map (illustrative)
Hover or focus any token to see its nearest neighbours. These 60 tokens are hand-placed to show the shape of the structure real embeddings have — clusters by role, and a consistent offset between related pairs. It is a teaching diagram, not a projection of GPT-2's weights.
overlay
numberspeople & rolesanimalscode keywordspunctuation
12374210019990.5threeseventwelvemillioncatdoghorsemousetigerwhaleeaglesheeprabbitsalmonlizardbeetle.,!?;:()defreturnimportclassifelseforwhileNoneTrueprintlambdaselfexceptkingqueenmanwomanboygirlprinceprincessactoractressuncleaunt

Switch the overlay to pair offsets: every arrow is the same length and direction, which is the property that makes vector arithmetic like king − man + woman land near queen. Real embeddings show a weaker, noisier version of this — see the caveat in the lesson above.

Nearest neighbours of king: man (5.3), boy (8.8), queen (10.0). In a real model these distances come from cosine similarity between rows of the embedding matrix, and the clusters are learned, never designed.

Things to try: (1) Drag the merge slider from 0 to 200 with the prose sample loaded and watch tokens fuse — at 0 merges this is a character-level model, and the token count falls by more than half by the end. (2) Switch to the numbers sample and look at how 1024 and 2048 get carved up; the corpus contains both, so ask yourself what an addition algorithm would have to learn from these shapes. (3) Type the same word twice, once after a space and once at the start of a line, and confirm they produce different tokens. (4) In the map, hover actor and 42 and notice that nearest-neighbour structure is about role in text, not meaning in the world.

Practice

Problem set

Problem 1 is the one to do on paper — running the merge loop by hand once is worth an hour of reading about it. The two code problems can share a notebook.

1.Run BPE by handpencil & paper

Corpus (word: count): low: 5, lower: 2, newest: 6, widest: 3. Start with characters as symbols; treat words as independent (no merges across word boundaries). Break count ties in favour of the pair encountered first, scanning words in the order listed.

  1. Carry out merges 1–4, writing the pair, its count, and the state of all four words after each merge.
  2. Using exactly those four merges in order, encode the unseen word lowest. How many tokens?
  3. What would the vocabulary need for lowest to be a single token, and why is that a bad trade?
2.Why merge order is part of the modelpencil & paper

A tokenizer has learned these merges, in this order: 0: t+h→th, 1: h+e→he, 2: th+e→the, 3: ·+the→·the (where · is a space).

  1. Encode ·the step by step. Which merges fire, and in which order?
  2. Now suppose merges 0 and 1 were swapped in rank. Encode ·the again. Do you get the same tokens?
  3. Explain why the at the start of a document and ·the mid-sentence are different tokens with different embedding vectors, and give one practical consequence for prompting.
3.Compare real tokenizersexplore

Open tiktokenizer and switch between models (GPT-2 and a modern GPT-4-class tokenizer at minimum). For each of the following, record the token count and the actual split:

  1. 1234567, 1,234,567, and 380 + 42 = 422
  2. The same sentence in English and in a non-Latin-script language you can get a translation of
  3. A short Python function, and the same function with the indentation doubled
  4. strawberry, and  SolidGoldMagikarp

Write two sentences per item on what the split predicts about model behaviour.

4.Implement BPE end to endcode

In a notebook, implement train(corpus, num_merges), encode(text) and decode(ids) for byte-level BPE. Train 500 merges on a few hundred KB of text (Tiny Shakespeare, or any file on your disk).

Success checks:

  1. decode(encode(s)) == s for a dozen strings including emoji, accented characters, and tabs.
  2. Compression: report characters per token before and after training. With 500 merges on English you should land around 3–4 characters per token, versus 1 at merge zero.
  3. Encode a word your corpus never contained and show the segmentation is sensible pieces rather than bare characters.
5.Three failures, traced to the tokenizerpencil & paper

Write a short paragraph on each of three real LLM failures that are caused or amplified by tokenization. For each: name the observable behaviour, give the mechanism at the token level, and state one intervention that would fix or reduce it. At least one of your three must be something you can reproduce yourself today.

6.Real embedding geometry in ten linescode

Load GPT-2 small in a notebook (transformers or TransformerLens) and pull out W_E, shape 50257×768.

  1. Verify the tying claim: is the unembedding matrix the same tensor as the embedding matrix?
  2. Compute cosine nearest neighbours for  king,  Paris,  seven, and def. Do the clusters from the widget show up?
  3. Compute the mean cosine similarity between 1,000 random token pairs. Compare with 1/768=0.0361/\sqrt{768} = 0.036 from Module 0.1. Explain any discrepancy.

Success check: nearest neighbours are recognisably related, and you can state whether real embeddings are more or less spread out than random directions.

0 of 6 problems marked done
Check

Check yourself

1.
Why do production LLMs use subword tokens rather than characters?
2.
A BPE tokenizer knows 0: t+h→th, 1: h+e→he, 2: th+e→the. Encoding the gives:
3.
Why did  SolidGoldMagikarp make GPT-2 and GPT-3 behave strangely?
4.
Which claim about tied embeddings is correct?
5.
A model fails to count the letters in strawberry. The most accurate diagnosis is:
6.
You compute cosine similarities between random rows of GPT-2's embedding matrix and get a mean around 0.15, not the 1/7680.0361/\sqrt{768} \approx 0.036 spread that random directions would give. What does that tell you?
7.
Your prompt ends with a trailing space. Why might that hurt output quality?
Answer all 7 questions to submit.
Submit your answers to complete this check.
Go deeper

Go deeper

Do the Karpathy video as a build-along; everything else here is either the primary source for a claim in the lesson or a tool you will keep open while prompting.

EssentialLet's build the GPT Tokenizervideo
Andrej Karpathy · 2024 · 2h (build-along)
Build a real byte-level BPE tokenizer, including the GPT-4 regex and special tokens. Do it with the code problem above open — the section on why encode() must pick the lowest-rank merge is the part people always get wrong on the first attempt. The last third (SentencePiece, vocabulary size choices) can be watched passively.
EssentialSolidGoldMagikarp (plus, prompt generation)blog
Jessica Rumbelow & Matthew Watkins · 2023 · 30 min
The founding document of glitch-token weirdness. Read the section on anomalous tokens and the transcripts closely; skim the prompt-generation method (it is interesting but separate). Ask yourself throughout: what other properties of a model could two mismatched training corpora produce?
Neural Machine Translation of Rare Words with Subword Unitspaper
Rico Sennrich, Barry Haddow & Alexandra Birch · 2016 · 40 min
The paper that brought BPE from data compression into NLP. Read §3 (the algorithm) and the worked example that matches the figure in the lesson; skip the machine-translation experiments unless you are curious about the pre-transformer era.
Fishing for Magikarp: Automatically Detecting Under-trained Tokens in LLMspaper
Sander Land & Max Bartolo · 2024 · 45 min
Glitch tokens grown up: automatic detection of under-trained tokens across many production models, using the model's own predictions rather than manual poking. Read the method section and the per-model results tables. The takeaway is that this is a live vocabulary-hygiene problem, not a GPT-2 anecdote.
Using the Output Embedding to Improve Language Modelspaper
Ofir Press & Lior Wolf · 2017 · 25 min
The tied-embeddings result: sharing input and output embeddings saves parameters and improves perplexity. Short and readable — read §2–3 and note the argument about what the two matrices are each trying to represent, because that shared geometry is what makes the logit lens work later.
Language Model Tokenizers Introduce Unfairness Between Languagespaper
Petrov, La Malfa, Torr & Bibi · 2023 · 30 min
Measures tokenized length for parallel text across many languages and finds differences up to 15×. Read the figures first — the disparity plot makes the argument on its own — then the discussion of cost, latency, and effective context. The clearest example in this module of a technical choice with a direct distributional-harm consequence.
tiktokenizertool
dqbd · 2023 · keep open
Paste any text, switch tokenizer, see the split and the ids. Use it whenever a model does something strange with numbers, whitespace, or a non-English string — checking the tokens is a ten-second first diagnostic that is right often enough to be a habit.