36 — Modern / LLM

Tokenization (BPE)#

NLPMathematical 1 min read
◆ The PatternHow text becomes numbers — the first step in every language model

Byte Pair Encoding (BPE) builds a vocabulary by iteratively merging the most frequent pair of tokens. It handles unseen words via subword splitting — no unknown tokens needed.

BPE: repeatedly merge most frequent adjacent pair
"lowest" → ["low", "est"] or ["l", "ow", "est"] depending on learned merges
Vocab size: typically 32k–128k tokens
GPT-2: 50,257  |  LLaMA: 32,000  |  GPT-4: ~100,000
// BPE merge process — watch vocabulary build up
1

Start with characters

Initial vocabulary = all unique bytes/characters in corpus

2

Count adjacent pairs

Find the most frequent pair of consecutive tokens

3

Merge & add to vocab

Replace all occurrences. New token added to vocabulary.

4

Repeat until vocab_size

Continue until target vocabulary size reached (e.g., 50k)

Why it matters: Tokenization determines the model's "eyesight". Poor tokenization (e.g., splitting numbers digit-by-digit) directly hurts performance. Modern models train their own tokenizer on their specific data.
Pattern bridge: Byte Pair Encoding merges frequent pairs into tokens — the same compression principle behind LLM vocabularies. In statistics, binning into percentiles is discretization of continuous data.
Worked example

Four words with counts: low ×5, lower ×2, newest ×6, widest ×3. BPE merges the most frequent adjacent pair each round: e+s, then es+t, then est+</w>, then l+o. After four merges “newest” is n e w est</w> — the common ending has become one token, learned from counts alone.

Where it misleads
  • Tokens are frequency artefacts, not morphemes; the same word can split differently with a leading space or capital.
  • Languages and scripts under-represented in the training corpus get more tokens per word, costing more and fitting worse.
  • Numbers split into irregular chunks, one reason arithmetic is hard for language models.
In code
from collections import Counter
words = {'l o w </w>': 5, 'l o w e r </w>': 2, 'n e w e s t </w>': 6, 'w i d e s t </w>': 3}   # word -> count
merges = []
for _ in range(4):
    pairs = Counter()
    for w, n in words.items():
        s = w.split()
        for a, b in zip(s, s[1:]): pairs[a, b] += n
    best = max(pairs, key=pairs.get)
    merges.append(''.join(best))
    words = {w.replace(' '.join(best), ''.join(best)): n for w, n in words.items()}
Python, in your browser — edit the code and run it again

Assumes import numpy as np. Each snippet carries its own example numbers; the comments say which are made up or simulated.

The same idea with a library
# tiktoken (OpenAI's fast BPE)
import tiktoken
enc = tiktoken.encoding_for_model("gpt-4")
tokens = enc.encode("Hello, world!")          # [9906, 11, 1917, 0]
text = enc.decode(tokens)                       # "Hello, world!"

# HuggingFace tokenizers
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b")
Sources
  • R. Sennrich, B. Haddow & A. Birch, “Neural Machine Translation of Rare Words with Subword Units”, ACL, 2016
  • P. Gage, “A New Algorithm for Data Compression”, C Users Journal 12(2), 1994
  • T. Kudo & J. Richardson, “SentencePiece: A Simple and Language Independent Subword Tokenizer and Detokenizer”, EMNLP, 2018

Last reviewed October 2026 · How this site checks its content · Report a mistake

Linked from 1
← Previous
GANs
Open in the full reader, with the topic sidebar