深入 Byte Pair Encoding 原理,手动实现训练、编码和解码
在上一章,我们了解到字符级 tokenization 的问题:序列太长,无法捕捉语言结构。那么,有没有一种方法,既能支持所有字符(通过 UTF-8 字节),又能压缩序列长度?
Byte Pair Encoding (BPE) 就是答案。
BPE 的核心思想非常简单:
迭代合并最频繁的字节对
从 UTF-8 字节序列开始,反复找到最常出现的相邻字节对,将它们合并成一个新的 token。重复这个过程,直到达到目标词汇表大小。
这样,常见的单词和短语会被合并成单个 token,而罕见的字符组合仍然保持为多个字节。
让我们通过一个简单的例子来理解 BPE。假设我们有一个简化的序列:
初始序列: a a a b d a a a b a c
词汇表: {a, b, c, d} (4 个 tokens)
统计所有相邻字节对的出现次数:
a a -> 4 次 ← 最频繁
a b -> 2 次
b d -> 1 次
d a -> 1 次
b a -> 1 次
a c -> 1 次
最频繁的是 a a,出现 4 次。我们创建一个新 token Z 来表示 a a:
合并后: Z a b d Z a b a c
词汇表: {a, b, c, d, Z} (5 个 tokens)
合并规则: Z = a a
序列长度从 11 减少到 9。
现在统计新序列中的字节对: