Concepts / Building a Minimal BPE Tokenizer from Scratch

Building a Minimal BPE Tokenizer from Scratch

Byte Pair Encoding is a tokenization method used in natural language processing, including in GPT-2.

  • Programming

Why Models Read Tokens Instead of Sentences

A language model does not read text as whole sentences. It reads a sequence of tokens, and something has to decide where one token ends and the next begins. That something is the tokenizer. The choice of tokenizer affects how much text fits into a model's input, how common words and rare words are represented, and how the model handles spellings it has never seen before.

This article builds a clear mental model of one tokenization method, Byte Pair Encoding, usually abbreviated BPE. The goal is to understand what happens step by step, so that the implementations and interactive demonstrations you meet later make sense. The central idea is small enough to trace by hand, and you will do exactly that below.

What BPE Is and Where It Is Used

Definition

Byte Pair Encoding is a tokenization method used in natural language processing. It is the method behind the tokenizer used to train GPT-2.

The name points to the core operation. A BPE tokenizer works on pairs of adjacent symbols and combines frequent pairs into single units. Repeating that combination step gradually builds a vocabulary of units that are longer than one character and shorter than a whole word. Because the units are pieces of words, BPE belongs to the family of subword tokenization methods.

The method has a well-known origin in machine translation. The research paper that introduced this approach is titled Neural Machine Translation of Rare Words with Subword Units. It was published in 2015 by Sennrich et al. and is available on arXiv. Its title states the motivation directly: rare words are the hard case, and subword units are the proposed way to handle them.

Why Subword Units Sit Between Two Extremes

There are two obvious ways to cut text into tokens, and both have costs. If a tokenizer treats every whole word as one token, it needs a huge vocabulary, and any word it has not seen during training has no entry at all. If it treats every character as one token, the vocabulary stays small, but the sequences become long and the individual units carry little meaning on their own.

Tokenization approachVocabulary sizeSequence lengthHandling of a word never seen in training
Whole words as tokensHugeShortNo entry exists for the word
Single characters as tokensSmallLongUnits carry little meaning on their own
Subword units (BPE)Between the twoBetween the twoAssembled from smaller pieces the vocabulary already holds

Where subword units fall relative to whole-word and character tokenization

Subword units resolve this tension. Common words can stay whole, while rare or unfamiliar words are assembled from smaller pieces that the vocabulary already contains. Subword units let a tokenizer represent a rare word by combining pieces it already knows, rather than needing a dedicated entry for that word.

Tracing One Merge on a Token Sequence

The core of BPE is a single operation repeated many times: look at the current sequence of units, find the adjacent pair that occurs most often, and replace every occurrence of that pair with one new unit. Before looking at a real corpus, trace one merge on a tiny example. Start with the symbol sequence l o w l o w l o t, which is the word-like pattern low, low, lot written as single characters with no spaces.

Worked example

One merge step on a character sequence

Starting from the symbols l o w l o w l o t, perform one BPE merge step and describe how the sequence changes.

  1. 1
    Count adjacent pairs

    Reading left to right, the adjacent pairs are lo, ow, wl, lo, ow, wl, lo, ot. The pair lo appears three times, ow appears twice, wl appears twice, and ot appears once.

  2. 2
    Pick the most frequent pair

    The pair lo has the highest count, so it is the one to merge. The other pairs are left alone for this step.

  3. 3
    Create the new unit and replace occurrences

    The pair lo becomes a single new unit called lo. Scanning left to right, each non-overlapping occurrence of l followed by o is replaced by lo. The three occurrences sit at positions 0, 3, and 6.

  4. 4
    Read the new sequence

    The sequence drops from nine symbols to six: lo w lo w lo t. The units at positions 0, 2, and 4 are now the merged unit, and the rest of the sequence is unchanged.

Result

After one merge, the sequence is lo w lo w lo t, and the vocabulary has gained one entry: lo. A unit longer than one character now exists and can be used as a building block for later merges.

lposition 0lomerged unitoposition 1wposition 1wposition 2lomerged unitlposition 3wposition 3oposition 4lomerged unitwposition 5tposition 5lposition 6oposition 7tposition 8mergedmergedmerged
Which adjacent pair is merged, and at which positions does the sequence change? The pair l and o, which occurs three times, becomes the single unit lo at each of its three positions.

Notice what did not change. The w and t symbols kept their positions in the sequence, and only the three occurrences of the pair lo were affected. This is the general pattern: a merge touches exactly the places where the chosen pair occurs, and everywhere else the sequence stays as it was. The new unit lo is now available, so a later merge can combine it with a neighbor, such as w, to form a longer unit.

Counting Pairs and Choosing the Next Merge

Choosing which merge to make is a counting problem. Each pass looks at the current sequence of units, counts how often each adjacent pair occurs, and selects the pair with the highest count. The selection rule is simple and is the same at every step: the most frequent adjacent pair is the one that gets merged. Each merge then adds one new entry to the vocabulary.

  1. 1
    Start from the current sequence of units, which at the beginning is just the basic symbols.
  2. 2
    Count every adjacent pair of units across the sequence.
  3. 3
    Select the pair with the highest count.
  4. 4
    Replace each occurrence of that pair with a single new unit.
  5. 5
    Record the new unit so that it can serve as a building block for later merges.

Repeating the Merge Loop

The loop between counting and merging is the heart of the method. A single merge only produces a unit two symbols long. Because each merged unit is then available as a building block, a later pass can merge a unit with a neighbor and produce something longer. Over many passes, units grow from single characters into longer pieces, which is how the vocabulary ends up holding units that are longer than one character.

l, o, w, tround 0: single charactersloround 1: merge l with olowround 2: merge lo with wmergemerge
How does repeating the merge process grow the vocabulary from single characters into longer subword units? Each round adds one merged unit that later rounds can build on.

In round 2 of this example, the sequence lo w lo w lo t contains the pair lo followed by w twice, so the walkthrough merges that pair into low. The longer unit low is a piece of a word, not a full word, and it was built entirely from the earlier merged unit lo. Real training runs over a large body of text and performs many merges, but the rule at each step is the same: find the most frequent adjacent pair, merge it, and record the new unit.

Training and Application as Two Stages

A BPE tokenizer is best understood as a pipeline with two distinct stages. Training builds the vocabulary: it starts from a basic set of symbols and performs the merge loop, recording each merge as one entry. Application uses the vocabulary that training produced to split new text into tokens. These are separate jobs, and mixing them up is a common source of confusion.

Raw texttraining corpusBasic symbolsstarting unitsCount adjacent pairsfrequency of each pairMerge most frequentpairone new unitLearned vocabularyone entry per mergeNew texttext to be tokenizedToken sequencecut using the vocabularysplit into symbolscount pairsselect top pairrecord unitused to splitinput
What are the stages from raw text to a learned set of merges and then to tokens for new text, and what passes between them?

The diagram shows the flow of data. Training takes raw text, works on its symbols, and produces a vocabulary with one entry per merge. Application takes that vocabulary and a new piece of text and cuts the text into tokens. The vocabulary is the link between the two stages, which is why it is the thing you save after training and reload later.

Mistakes Beginners Make with BPE

  • Common mistake

    Starting the merge process from whole words

    What it looks like

    Beginning with the words low and lot as the initial units and trying to merge them

    Why it fails

    BPE starts from a basic set of symbols. Whole words are the thing a subword method is designed to avoid needing as dedicated entries.

    Do this instead

    Start from the basic symbols, such as single characters, and let frequent pairs build longer units.

  • Common mistake

    Merging the least frequent pair

    What it looks like

    In the sequence l o w l o w l o t, choosing ot (count 1) because it looks unusual

    Why it fails

    The selection rule is to merge the most frequent adjacent pair. Picking a rare pair does not follow that rule.

    Do this instead

    Count every adjacent pair and merge the one with the highest count.

  • Common mistake

    Treating training and application as the same step

    What it looks like

    Expecting that tokenizing new text will add new merges to the vocabulary

    Why it fails

    Training is the stage that builds the vocabulary. Application uses a vocabulary that already exists to split new text.

    Do this instead

    Build the vocabulary during training, then reuse it unchanged when splitting new text.

  • Common mistake

    Expecting a single merge to produce a long word-sized unit

    What it looks like

    Expecting one merge of l and o to produce low

    Why it fails

    Each merge combines exactly two adjacent units. Longer units come from many rounds, with each round building on earlier merged units.

    Do this instead

    Repeat the counting and merging loop, so that merged units can combine with neighbors in later rounds.

  • Common mistake

    Forgetting that a merge changes only the positions where the chosen pair occurs

Where to Inspect or Build a BPE Tokenizer

Once the mental model is clear, there are resources that let you go further. The source material points to three concrete resources, and each suits a different goal: moving from the concept to real code, or moving from the concept to a visual demonstration. The reading that started it all is the 2015 paper by Sennrich et al., available on arXiv, which explains why subword units were proposed for rare words in machine translation.

  • Read the original paper, Neural Machine Translation of Rare Words with Subword Units, on arXiv to understand the motivation behind the method.
  • Use a real code implementation to see the counting and merging loop running on actual text.
  • Use an interactive visual demonstration to watch pairs being counted and merged step by step.
  • Compare the three resources against your own hand traces to check that you understand the merge rule.

Predicting the First Merge

What do you think happens?

Given the symbol sequence a a a b, which pair is merged first, and what is the sequence afterward?

  • The pair ab is merged, giving a a a b

  • The pair aa is merged, giving aa a b

  • The pair ba is merged, giving a a ba

Reveal answer
Answer:

The pair aa is merged, giving aa a b

The adjacent pairs are aa, aa, and ab. The pair aa occurs twice and ab occurs once, so aa is the most frequent pair. Scanning left to right, the first two symbols form a non-overlapping occurrence and become aa, leaving a and b after it.

MEDIUM

Take the symbol sequence c a t c a t c o t. Count every adjacent pair, identify the most frequent pair, and write the sequence after one merge of that pair. Then state how many entries the vocabulary gains and which positions changed.

Hints
  • List all adjacent pairs first, reading from left to right, before deciding anything.
  • Two positions in the original sequence are the start of the pair you are merging; check how many occurrences there are.
  • Only the positions where the chosen pair occurs should change.

Key Takeaways

  • BPE is a tokenization method, used in natural language processing and in the tokenizer behind GPT-2, that builds subword units by repeatedly merging the most frequent adjacent pair of symbols.
  • Subword units sit between whole-word and character tokenization, letting common words stay whole while rare words are assembled from smaller pieces already in the vocabulary.
  • Each merge counts adjacent pairs, selects the most frequent one, replaces its occurrences with a single new unit, and adds one entry to the vocabulary.
  • Training builds the vocabulary through the merge loop; application uses that vocabulary to split new text into tokens.
  • The open-source resources to explore are the original 2015 paper, real code implementations, and interactive visual demonstrations.

Related concepts

More concepts starting with B