Before you start
Learn the merge rules that every modern tokenizer is built from.
You are given words, a dict mapping a word to how often it appears. Start with
each word split into single characters. Then repeat num_merges times:
Stop early if no pair occurs more than once, or if no pairs remain.
Return the list of merges in order, each a tuple (left, right).
Two things to be careful about:
a a a, merging (a, a)
produces aa a, not aa plus a dangling symbol. Scan with an index and skip
two positions when you merge.This is why a subword vocabulary has no unknown tokens: common words end up as single symbols, rare ones fall back to pieces, and anything at all can be spelled out from characters.
def train_bpe(words, num_merges):
Input
words = {"low": 5, "lower": 2}
train_bpe(words, 2)
Output
[('l', 'o'), ('lo', 'w')]
Reasoning
Weighted pair counts are (l, o): 7, (o, w): 7, (w, e): 2 and (e, r): 2. (l, o) and (o, w) tie, and (l, o) is smaller, so it merges first. After that, (lo, w) occurs 7 times and merges next.
Check runs the visible cases against a fresh kernel. Submit runs the hidden ones too.
⇧↵run cell