BPE 分词器身上一直背着"数据压缩算法"的标签——它 1994 年的原始论文确实是发在压缩领域的。但"压缩算法"这个归类太宽泛:哈夫曼编码、算术编码、LZ 系字典压缩都是压缩,机制天差地别。要看清 BPE 在压缩谱系里的真实位置,最好的参照物是 LZ78:它和 BPE 做着同一件事(建字典、用短码替换高频子串),却走向了两个不同的工程极端。把两者放进同一个框架对比,BPE 的每个设计选择都能得到解释。
同一个问题:最小描述长度
两个算法都在优化同一个目标。给定字符串 $s$,一种编码方式 $C$ 的总成本是
$$ L(s, C) = \underbrace{-\log P(s\mid C)}_{\text{编码正文}} + \underbrace{\mathrm{cost}(C)}_{\text{字典自身的成本}}. $$
这就是最小描述长度(MDL)原则:好的压缩 = 短的正文 + 便宜的字典。字典压缩的共同思路是让字典条目出现在正文里时只花 $\log V$ 的索引成本($V$ 是字典大小),只要条目足够高频,这个账就划算。BPE 和 LZ78 的分歧从下一步开始:字典怎么建、正文怎么解析。
LZ78:在线、顺序、一鱼一码
LZ78(Ziv & Lempel, 1978)的解析规则:从左到右扫描输入,每一步取当前字典里能匹配的最长前缀,输出 (字典索引, 下一个字符) 二元组,然后把"匹配串 + 该字符"整体加入字典。字典是这条流私有的、边解析边生长的。
拿 ababcaba 走一遍(字典初始为空,索引 0 表示"空前缀"):首字符 a 无匹配,输出 (0, a),字典加入 a→1;b 同理输出 (0, b),字典 b→2;接下来扫描到 abca...,最长匹配是字典里的 a(索引 1),追加一个字符得 ab,输出 (1, b),字典 ab→3;c 输出 (0, c),字典 c→4;最后 aba:最长匹配 ab(索引 3),追加 a,输出 (3, a),字典 aba→5。全程 5 个二元组,字典 5 条。
两个性质值得记住。前缀封闭:字典里每个条目都是某个前缀加一字符,这是"最长匹配 + 追加一字符"构造的直接结果。顺序依赖:ab 能进字典,完全因为它恰好在那个位置被解析出来;同样的子串换个上下文出现,解析历史不同,字典也不同。字典是流的偶然产物,不是语料的全局统计产物。
BPE:离线、全局、频率贪心
BPE 的做法在前面文章里讲过(3010),放进这个框架重新表述:字典不是从任何一条具体流里长出来的,而是从整个语料的频率统计里贪心选出来的——每轮选出现次数最多的相邻对合并,精确地最大化"当前这轮的正文缩短量"。对比 LZ78,差异是结构性的:
| 维度 | LZ78 | BPE |
|---|---|---|
| 字典来源 | 单条流的解析历史 | 全局语料频率统计 |
| 解析方式 | 顺序贪心,最长匹配 | 规则表优先级匹配 |
| 字典复用 | 每条流私有,随流丢弃 | 全局共享,随模型发布 |
| 条目性质 | 前缀封闭 | 任意子串,无封闭性 |
| 失败模式 | 冷启动:新流前期字典空,压缩率差 | 尾部条目低频,语料外文本退化 |
BPE 的"离线"是关键一步棋。压缩工具的输入是任意流,没法提前看全局统计,只能在线建字典;分词器的输入分布相对固定(人类语言),值得也有条件先花一遍扫描的代价,把全局最优的贪心近似拿到手。这不是算法 smarter,是问题设定 different:压缩要处理任意数据,分词只服务一个分布。
贪心之外的压缩智慧:BPE 没继承的部分
成熟的压缩工具并不满足于纯贪心解析,它们的两项改进值得 BPE 借鉴——也确实被借鉴了。
最优解析(optimal parsing)。LZ 系的贪心最长匹配不是最优的:有时"故意短匹配"能让后续内容用上新字典条目,全局更省。zstd 等现代压缩器用 lazy matching(多看一个位置,权衡长短匹配)逼近最优。BPE 编码侧是纯规则表匹配,没有"为后续省钱"的概念;它的最优性保证只到"训练时贪心选的合并"为止。Unigram 分词器在这个意义上更"压缩正统":它显式最大化语料的边际似然,等价于在切分格子上做了一次全局最优解析。
字典成本的显式建模。MDL 公式的第二项 $\mathrm{cost}(C)$——字典自身的存储成本——LZ78 不需要管(字典随流丢弃、不存储),BPE 也不怎么管(词表成本被摊进嵌入参数,见 3050 的账本)。但分词场景里这项成本真实存在:词表每多一个条目,嵌入矩阵多一行、训练样本被稀释一份。压缩理论预言的"字典存在最优大小"在分词器上同样成立,这就是词表不能无限大的信息论根源。
算术编码的视角。把分词看成编码,token 序列就是原文的一种码字。BPE 的码字是"字典索引序列",每个索引等长($\log V$ 比特)——这是定长码,对频率倾斜的分布是浪费的。Unigram 的概率模型允许按 $p(x)$ 变长编码(算术编码的思想),理论上更贴近熵极限。分词器没走这一步,因为后续 Transformer 需要等长的嵌入查找,变长码的收益换不来——又一次"问题设定 different"的例证。
这个视角能预测什么
理论框架的价值在于可证伪的预测,这个框架给出三条,都与实测吻合。其一,边际收益递减:字典条目按频率降序进入,正文的缩短量随条目数指数衰减,词表翻倍只省几个百分点(3010 的压缩曲线)。其二,语料外退化:BPE 的字典是全局语料的统计快照,遇到分布外文本(新语言、乱码、代码风格剧变)时条目失配,token 数暴涨——实测中低资源语言 token 膨胀三倍起。其三,Unigram 应更高效:显式似然 + 全局最优解析在压缩意义下严格优于贪心合并,实测的压缩率对比确实小幅领先,但编码侧的训练成本和速度劣势抵消了收益——这解释了为什么 BPE 仍是主流。
小结
BPE 和 LZ78 是同一场 MDL 优化的两个极端解:LZ78 在线、顺序、前缀封闭,字典是解析历史的副产品;BPE 离线、全局、频率贪心,字典是语料统计的冻结快照。分词器从压缩借来了框架,却因为服务对象单一(人类语言)、下游需求刚性(等长嵌入、确定性编码),主动放弃了压缩工具的最优解析和变长编码。看清了这条谱系,"BPE 为什么这样设计"的每个答案都有了出处。