BPE(Byte Pair Encoding,字节对编码)是一种子词级(Subword-level)分词算法,核心思想是通过迭代合并高频出现的字符或子词对,生成更高效的词汇表,平衡 “词汇表大小” 与 “语义表达精度”。它广泛应用于自然语言处理(NLP)的预训练模型(如 BERT、GPT、T5)中,尤其适合处理多语言、低频词和生僻词场景。
在 NLP 中,文本处理的第一步是 “分词”,传统分词方案存在明显缺陷,BPE 的出现正是为了解决这些问题:
BPE 的本质是 **“从最小单位开始,逐步合并高频组合”**:
- 初始单位:以 “字符” 作为最基础的子词(如英文初始词汇表为所有字母、数字、标点符号);
- 迭代合并:每次扫描所有文本,找到出现频率最高的 “字符对” 或 “子词对”,将其合并为一个新的子词,加入词汇表;
- 终止条件:重复合并过程,直到满足预设条件(如词汇表达到指定大小、合并次数达到阈值、高频对频率低于阈值)。
通过这一过程,高频词会被合并为完整词(如 “the”“and”),中频词拆为少量子词(如 “apple”→“app”+“le”),低频词拆为更多子词(如 “unhappiness”→“un”+“happi”+“ness”),既控制了词汇表大小,又减少了 OOV。
下面通过一个具体案例,拆解 BPE 的每一步操作,帮助理解其细节。
假设我们有一段简单的训练文本(已做基础预处理,如小写、分割为词):
"low low low lowly lower newer newer"
首先,将每个词拆分为 “字符序列 + 终止符</w>
”(终止符用于区分 “词尾子词” 和 “词中间子词”,如 “low” 的 “low</w>” 与 “lowly” 的 “low”),并统计每个词的出现频率:
low</w>
: 3 次(对应 3 个 “low”)
lowly</w>
: 1 次(对应 1 个 “lowly”)
lower</w>
: 1 次(对应 1 个 “lower”)
newer</w>
: 2 次(对应 2 个 “newer”)
初始词汇表(所有字符 + 终止符)为:
{l, o, w, </w>, y, e, r, n}
遍历每个词的字符序列,统计相邻子词对(初始为字符对)的出现次数:
- 对
low</w>
(3 次):(l,o)、(o,w)、(w,</w>) → 各贡献 3 次
- 对
lowly</w>
(1 次):(l,o)、(o,w)、(w,l)、(l,y)、(y,</w>) → 各贡献 1 次
- 对
lower</w>
(1 次):(l,o)、(o,w)、(w,e)、(e,r)、(r,</w>) → 各贡献 1 次
- 对
newer</w>
(2 次):(n,e)、(e,w)、(w,e)、(e,r)、(r,</w>) → 各贡献 2 次
汇总后高频对如下(仅列关键对):
选择频率最高的对(若有并列,任选其一,此处选(l,o)
),将其合并为新子词lo
,加入词汇表。
此时词汇表更新为:{l, o, w, </w>, y, e, r, n, lo}
接着,用新子词lo
替换所有词序列中的(l,o)
对,更新后的词序列为:
low</w>
→ lo
+ w
+ </w>
lowly</w>
→ lo
+ w
+ l
+ y
+ </w>
lower</w>
→ lo
+ w
+ e
+ r
+ </w>
newer</w>
→ n
+ e
+ w
+ e
+ r
+ </w>
假设我们设定 “词汇表大小达到 12” 为终止条件(初始 8 个,需合并 4 次),后续迭代过程如下:
- 统计新序列的子词对频率,发现
(lo, w)
频率最高(3+1+1=5);
- 合并为新子词
low
,加入词汇表(此时词汇表大小 9);
- 替换词序列中的
(lo, w)
为low
,如low</w>
→low
+</w>
。
- 统计新序列,
(low, </w>)
频率最高(3 次);
- 合并为
low</w>
,加入词汇表(大小 10);
- 替换后
low</w>
→low</w>
(完整词)。
- 统计新序列,
(e, r)
频率最高(1+2=3);
- 合并为
er
,加入词汇表(大小 12,满足终止条件);
- 替换后
lower</w>
→low
+e
+er
+</w>
,newer</w>
→n
+e
+w
+er
+</w>
。
- 最终词汇表:
{l, o, w, </w>, y, e, r, n, lo, low, low</w>, er}
- 最终分词结果:
- "low" →
low</w>
- "lowly" →
low
+ l
+ y
+ </w>
- "lower" →
low
+ e
+ er
+ </w>
- "newer" →
n
+ e
+ w
+ er
+ </w>
BPE 的解码是 “分词的逆过程”:将模型输出的子词序列,通过以下规则还原为原始文本:
- 直接拼接所有子词;
- 遇到终止符
</w>
时,将其替换为 “空格”(或直接删除,根据预处理规则);
- 最终去除多余空格,得到完整句子。
例如,子词序列[low</w>, low, l, y</w>]
解码后为:low lowly
。
BPE 的核心逻辑被后续算法优化,衍生出多种子词分词方案,各有侧重:
- 控制词汇表大小:避免词级分词的 “百万级词汇表”,降低模型参数量和训练成本;
- 减少 OOV 问题:低频词、新词可拆分为已有子词,几乎无未登录词;
- 语义连贯性:合并的子词通常具有语义关联(如 “un-”“-ness”),帮助模型学习词法规律;
- 多语言适配:无需针对不同语言设计特殊分词规则(如中文可直接以字符为初始单位)。
- 依赖训练数据:若训练数据覆盖不足,可能生成不合理的子词(如低频词拆分为过细的字符);
- 固定合并规则:一旦训练完成,分词规则固定,无法动态适应新领域的词汇(需重新训练分词器);
- 处理效率:长文本分词时,需遍历子词对统计频率,效率低于词级分词。
- 大语言模型(LLM)预训练:BERT、GPT、T5 等模型均以 BPE 或其变体作为基础分词方案,支撑千亿级参数模型的训练;
- 多语言 NLP 任务:如机器翻译、跨语言文本分类,通过子词统一多语言词汇表,减少语言间差异;
- 低资源语言处理:小语种文本量少,词级分词 OOV 严重,BPE 的字符级初始单位可有效解决这一问题;
- 特殊领域文本:如生物医药、法律文本(含大量专业术语),BPE 可将生僻术语拆分为可解释的子词,提升模型理解能力。
综上,BPE 作为子词分词的奠基算法,通过 “迭代合并高频对” 的核心逻辑,成为 NLP 预训练模型的 “标配” 技术之一,其思想也为后续分词算法的发展提供了重要参考。