深入 Byte Pair Encoding 原理,手动实现训练、编码和解码

BPE 算法的核心思想

在上一章,我们了解到字符级 tokenization 的问题:序列太长,无法捕捉语言结构。那么,有没有一种方法,既能支持所有字符(通过 UTF-8 字节),又能压缩序列长度?

Byte Pair Encoding (BPE) 就是答案。

BPE 的核心思想非常简单:

迭代合并最频繁的字节对

从 UTF-8 字节序列开始,反复找到最常出现的相邻字节对,将它们合并成一个新的 token。重复这个过程,直到达到目标词汇表大小。

这样,常见的单词和短语会被合并成单个 token,而罕见的字符组合仍然保持为多个字节。

BPE 算法步骤

让我们通过一个简单的例子来理解 BPE。假设我们有一个简化的序列:

初始序列: a a a b d a a a b a c
词汇表: {a, b, c, d}  (4 个 tokens)

第 1 轮:找到最频繁的字节对

统计所有相邻字节对的出现次数:

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。

第 2 轮:继续合并

现在统计新序列中的字节对: