Byte-Pair Encoding (BPE) is a text tokenization technique in Natural Language Processing. It represents words as smaller units called subwords or tokens by repeatedly merging frequent adjacent symbols during training.

This technique helps in handling rare or unknown words by breaking them into smaller parts that the model has already learned during training. By reducing the vocabulary size, it makes it easier to work with large amounts of text while allowing the model to understand wide variety of languages.
BPE converts text into tokens. The resulting tokens can then be mapped to token IDs and processed by an NLP or language model.
Working
- BPE starts by representing each word as a sequence of individual characters or initial tokens. It then repeatedly finds the most frequent pair of adjacent tokens and merges them into a single subword token. The process continues until the desired number of merges or vocabulary size is reached.
- Suppose we have a text corpus with four words: "ab", "bc", "bcd" and "cde".
Step 1: Initialize the vocabulary
Each word is initially split into individual characters.
Vocabulary = {"a", "b", "c", "d", "e"}
Step 2: Count token frequencies
The frequency of each character in the corpus is calculated:
Frequency = {"a": 1, "b": 3, "c": 3, "d": 2, "e": 1}
Step 3: Find the most frequent adjacent pair
BPE examines consecutive tokens and finds the pair that occurs most frequently.
Most frequent pair is "bc" with a frequency of 2.
Step 4: Merge the pair
The pair "bc" is merged into a single subword token.
Merge "b" and "c" to create a new subword unit "bc".
The token sequences are now updated.
For example:
"bcd" : "bc" + "d"
Step 5: Repeat the process
The frequencies of adjacent token pairs are recalculated using the updated sequences. The most frequent pair is then merged again.
For example:
The next merges may produce tokens such as"cd", "de", "ab" or "bcd", depending on their frequencies.
Each learned merge adds a new subword unit to the vocabulary. The process continues until the desired vocabulary size or number of merges is reached.
Step 6: Represent words using the learned subwords
After learning the merge rules, words are represented using the resulting subword tokens.
For example:
"ab" -> "a" + "b"
"bc" -> "bc"
"bcd" -> "bc" + "d"
"cde" -> "c" + "de"
The same learned merge rules can then be applied to new words. This allows BPE to represent common words as larger subwords while breaking rare or unseen words into smaller known units.
Implementation
1. Importing Libraries
We use Counter from the collections module to count the frequency of adjacent token pairs.
from collections import Counter
2. Counting Adjacent Token Pairs
The get_pair_frequencies() function counts how often each adjacent pair occurs in the current tokenized vocabulary.
def get_pair_frequencies(vocab):
pairs = Counter()
for tokens in vocab.values():
for i in range(len(tokens) - 1):
pair = (tokens[i], tokens[i + 1])
pairs[pair] += 1
return pairs
Here, vocab contains each word as a sequence of its current tokens. The function examines consecutive tokens and stores their frequencies in a Counter.
3. Merging a Token Pair
The merge_pair() function replaces every occurrence of a selected pair with a single merged token.
def merge_pair(vocab, pair):
new_vocab = {}
for word, tokens in vocab.items():
new_tokens = []
i = 0
while i < len(tokens):
if i < len(tokens) - 1 and (tokens[i], tokens[i + 1]) == pair:
new_tokens.append(tokens[i] + tokens[i + 1])
i += 2
else:
new_tokens.append(tokens[i])
i += 1
new_vocab[word] = new_tokens
return new_vocab
For example, if the selected pair is ("b", "c"), the token sequence:
["b", "c", "d"]
becomes:
["bc", "d"]
4. Learning BPE Merge Rules
The learn_bpe() function initializes each word as a sequence of characters and repeatedly finds and merges the most frequent adjacent pair.
def learn_bpe(corpus, num_merges=3):
vocab = {
word: list(word)
for word in corpus.split()
}
merges = []
for _ in range(num_merges):
pair_frequencies = get_pair_frequencies(vocab)
if not pair_frequencies:
break
most_frequent = max(
pair_frequencies,
key=pair_frequencies.get
)
merges.append(most_frequent)
vocab = merge_pair(vocab, most_frequent)
return merges
The learned pairs are stored in merges in the order in which they were selected. After each merge, the vocabulary is updated before calculating the frequencies for the next merge.
5. Applying the Learned BPE Rules
The apply_bpe() function applies the learned merge rules to a new word.
def apply_bpe(word, merges):
tokens = list(word)
for pair in merges:
new_tokens = []
i = 0
while i < len(tokens):
if i < len(tokens) - 1 and (tokens[i], tokens[i + 1]) == pair:
new_tokens.append(tokens[i] + tokens[i + 1])
i += 2
else:
new_tokens.append(tokens[i])
i += 1
tokens = new_tokens
return tokens
The function starts with individual characters and applies each learned merge rule in order to produce the final subword tokens.
6. Example Usage
We now use a small corpus to learn three BPE merge rules and apply them to the word bcd.
# Example corpus
corpus = "ab bc bcd cde"
# Learn 3 merge rules
merges = learn_bpe(corpus, num_merges=3)
print("Learned merges:", merges)
# Apply the learned rules to a new word
word = "bcd"
tokens = apply_bpe(word, merges)
print("BPE representation:", tokens)
Output:
Learned merges: [('b', 'c'), ('a', 'b'), ('bc', 'd')]
BPE representation: ['bcd']
The first merge combines b and c because this pair occurs most frequently in the corpus. The subsequent merge rules are learned from the updated token sequences. When the learned rules are applied to bcd, b and c are first merged into bc, followed by bc and d, resulting in the token bcd.
Note: Run the complete code together, as the functions depend on one another.
You can download the complete source code from here.
Applications
- Large Language Models: Used to split text into subword tokens before processing.
- Machine Translation: Helps represent words across languages, including rare and morphologically complex words.
- Text Generation: Provides a manageable vocabulary while allowing new words to be represented through subword combinations.
- Text Classification: Converts text into subword tokens that can be used as model inputs.
- Speech and Language Processing: Helps handle varied and previously unseen word forms.
Limitations
- Token boundaries are based on corpus statistics rather than linguistic meaning.
- Different training corpora produce different vocabularies and merge rules.
- Tokenization can be inefficient for some languages or domains if the vocabulary is poorly trained.
- The learned vocabulary and merge rules are tokenizer-specific.