想象你经营着一家乐高积木工厂,每周要交付城堡、飞船、游乐园等几百款不同的模型。一开始,每款模型都从单颗粒积木开始拼装,老师傅们累得直不起腰,仓库也堆满了形形色色的零件。后来厂长发现一个窍门:不同订单里“窗户+门框”“车轮+车轴”这些组合反复出现,为什么不提前把最畅销的组合铸成一体化的预制件呢?工期立刻缩短,返工也变少了。这正是 BPE(字节对编码)的智慧——它是今天几乎所有大语言模型(GPT、BERT、Llama)在读取文本前的“第一道工序”。 BPE 先把文本拆成最小的“字符积木”,再统计哪些相邻字符对出现得最频繁,然后像开模具一样把它们逐一合并成“子词预制件”。最终构建出一本不大不小的“词表模具库”:既能覆盖绝大多数真实词汇,又不怕碰到词典里没有的生僻词——任何生词都能拆成预制件和散装颗粒拼出来。本教程会带你从“为什么要子词”讲到 BPE 的流水线、编码解码、预训练模型中的应用和变体算法,最后用 Python 亲手实现一个迷你 BPE,彻底看懂 GPT 分词器背后的“预制件工厂”。

岗位关联

对 AI 从业者:BPE 是 NLP 管线中最底层的地基,掌握它能让你在模型选型、Tokenizer 调优和多语言部署中做出真正专业的决策,是通往大模型内部原理的必经之门。

目录
  1. 可视化演示
  2. 什么是BPE
  3. 词表与OOV
  4. 算法流程
  5. 编码与解码
  6. 预训练模型
  7. 改进变体
  8. 实际应用
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示系统处理流水线、实时性能指标曲线及多方案对比分析,包含数据流转、吞吐延迟监控与方案评估。

本节配有交互动效(进入视口后自动加载,约 3KB)。

系统可视化 处理流程:输入→处理→模型→输出 性能监控:实时指标 P=L×T

什么是BPE

你经营的乐高工厂每周要交付几百款不同的模型,一开始每款都从单颗粒拼起,老师傅们腰都直不起来。厂长发现,不同订单里“窗户+门框”“车轮+车轴”这些组合反复出现,干脆提前把最畅销的组合铸成一体化的预制件——工期缩短,返工也少了。BPE 把这套“预制件思维”带进了自然语言处理。

BPE 全称 Byte Pair Encoding(字节对编码),最早是 Gage 在 1994 年提出的数据压缩算法。2016 年,Sennrich 等人把它引入 NLP,用来构建“子词词表”。它的做法和工厂一模一样:先把语料拆成最小单位(字符或字节),统计所有相邻字符对的出现频率,把最高频的那对“预装”成一个新词元。重复这个过程,就得到一套子词预制件,也就是子词词表。

为什么需要子词?词级方案(按空格切分)词表动辄几十万,还频繁遇到词典里没有的未登录词;字符级方案不会漏词,但一个单词被拆成一串字符,序列变长、计算开销大,语义单元也太碎。BPE 在两者之间取平衡:高频词整体保留,低频词拆成常用子词,实在不认识的词还能拆到字符兜底。从压缩角度看,它把 “lowest“ 从 6 个字符压成 ”low” + "est" 两个词元,本质是一种词典压缩。

工厂只给“卖得最好”的组合开模具,BPE 只给“出现最多”的字符对合并——每一次决策都由数据说了算,这就是子词词表诞生的全部秘密。

p∗=arg⁡max⁡p∈Pcount(p)p^{*} = \arg\max_{p \in P} \text{count}(p)
每一轮合并,BPE 只做一件事:在全部相邻字符对里,挑出现次数最多的那对,合并成一个新词元。
  1. 候选对集合 P语料中所有相邻字符或词元的组合构成的集合,比如 "l o"、"o w"、"e s" 都是候选对。
    P={(a,b)∣a,b 为相邻字符}P = \{(a, b) \mid a, b \text{ 为相邻字符}\}
  2. 频次统计 count(p)统计每个候选对在全语料中出现的总次数,统计时按每个词的词频加权。
    count(l,o)=3\text{count}(l, o) = 3
  3. 最优对 p\*argmax 表示取使 count 最大的那一对,作为本轮合并的对象,合并后它会变成一个独立的词元。
    p∗=arg⁡max⁡p∈Pcount(p)p^{*} = \arg\max_{p \in P} \text{count}(p)

词表与OOV

模具不是白造的:每副模具都占仓库储位、需要保养维护。厂长最头疼的是储位到底留多少——留太多,库存成本和开模费爆炸;留太少,热销件缺货,订单只能干等。BPE 的聪明之处在于,“模具数量”完全由“合并次数”这一个旋钮控制。

词表大小等于初始字符集加上合并次数。初始字符集通常只有几百个(字符或字节),每合并一次就多一个新词元。想要覆盖更复杂的文本,就多合并几轮;想要省内存,就少合并几轮,这就是词表规模与覆盖能力的平衡。OOV(Out-of-Vocabulary,未登录词)指模型词表里没有的词——传统词级方案中,专有名词、拼写变体、emoji 都会触发 OOV。而在 BPE 下,任何生词都能被切分为词表中的子词,最坏情况到单字符兜底,OOV 率趋近于零,词表却能保持在几万级别的可控范围。

老板要开多少副模具直接决定仓库多大——BPE 把词表大小变成了一个由合并轮数精确控制的旋钮,“词表预算”从此不再失控。

∣V∣=∣Vchar∣+nmerge|V| = |V_{\text{char}}| + n_{\text{merge}}
BPE 词表只有两个来源:初始字符集 + 合并产生的新词元,所以词表大小和合并次数严格挂钩,可预测、可调节。
  1. 初始字符集 |V_char|训练语料中去重后的字符(或字节)总数,比如中英文混合语料的字符集通常几百到几千。
    Vchar={c1,c2,…,cm}V_{\text{char}} = \{c_1, c_2, \dots, c_m\}
  2. 合并轮数 n_merge训练时预设的合并次数,每执行一次合并就向词表新增一个词元。
    ΔV=nmerge\Delta V = n_{\text{merge}}
  3. 词表大小 |V|最终子词词表的规模,等于初始字符数加合并轮数;这个公式让“词表预算”变得精确可控。
    ∣V∣=∣Vchar∣+nmerge|V| = |V_{\text{char}}| + n_{\text{merge}}

算法流程

铸模车间有条雷打不动的四班流程:先盘点零件,再统计销量,接着开新模具,最后更新产品图纸。第二天必须重新盘点,因为新模具诞生后,畅销组合可能变了。BPE 的训练流程正是这个循环。

具体四步:第一步,初始化——把语料的每个词拆成字符序列,并加上单词结束符 </w> 用于标记词边界。第二步,统计——扫描全部词,统计每个相邻字符对的频次,统计时乘以词频加权。第三步,合并——选出频次最高的字符对,合并成一个新词元,替换语料中所有出现的位置。第四步,停止——达到预设合并轮数后输出合并规则表。关键点在于:每轮合并后必须重新统计,因为新词元和邻居又形成了新的相邻对,最优组合会动态变化。

上周“窗+框”组合卖爆合并成预制件之后,这周“框+玻璃”可能成为新销冠——BPE 每轮都重新“看数据”,而不是抱着一张旧统计表不放。

seq(t+1)=Merge(seq(t), pt∗),pt∗=arg⁡max⁡pft(p)\text{seq}^{(t+1)} = \text{Merge}\left(\text{seq}^{(t)},\ p_t^{*}\right), \qquad p_t^{*} = \arg\max_{p} f_t(p)
第 t 轮先统计当前语料的相邻对频次 f_t,选出最优对 p\* 完成合并,得到新语料后进入第 t+1 轮,如此循环直到停止。
  1. 初始序列 seq⁽⁰⁾每个词被拆成独立字符的序列,如 “low“ 变成 ”l o w </w>”。
    seq(0)=[l,o,w,⟨/w⟩]\text{seq}^{(0)} = [l, o, w, \langle /w \rangle]
  2. 每轮统计 f_t(p)在第 t 轮重新统计所有相邻对的频次,注意是新语料上的统计。
    ft(p)=countt(a,b)f_t(p) = \text{count}_t(a, b)
  3. 合并操作 Merge把最优对 p_t\* 的所有出现替换为单个词元,如 “e s“ 合并为 ”es”。
    Merge(seq, pt∗)=seq 中所有 pt∗ 变为词元\text{Merge}(\text{seq},\ p_t^{*}) = \text{seq 中所有 } p_t^{*} \text{ 变为词元}
  4. 迭代循环重复“统计-合并”,直到达到预设的合并轮数 n_merge,输出合并规则表。
    repeat t=1,2,…,nmerge\text{repeat } t = 1, 2, \dots, n_{\text{merge}}

编码与解码

有了预制件,工厂还得教会工人两件事:新图纸怎么按模具库组装(编码),退货怎么拆箱验收(解码)。组装时优先找整块预制件,找不到就找最大的局部,实在没有就用散装颗粒;验货时把所有构件按顺序拼回去,原样还原即可。

编码阶段,给定任意句子,BPE 按词表从左到右做贪心最长匹配切分——优先匹配最长的词元,匹配不到就降级到更短词元,最终一定能拆到字符级,因此永远不会遇到“拆不动”的词。输出是词元 id 序列,交给模型。解码阶段,把 id 查回词元字符串,按序拼接(去掉边界标记)即还原原词。训练得到的合并规则表(哪对合并成了哪个词元)是整个过程的“模具清单”,编码解码都要用到它,所以 BPE 是一个无损、可逆的过程。

组装工永远能找到零件——大到预制件、小到散颗粒,总能拼出图纸上的模型。这就是 BPE 面对“从未见过的新词”也毫不慌张的底气。

w=u1⊕u2⊕⋯⊕ukw = u_1 \oplus u_2 \oplus \cdots \oplus u_k
解码就是把编码得到的 k 个子词按顺序做字符串拼接,拼完再剔除边界标记,就能完整还原原始单词,信息不丢失。
  1. 词元序列编码阶段输出的 k 个子词,如 ["low", "er"]。
    w↦(u1,u2,…,uk)w \mapsto (u_1, u_2, \dots, u_k)
  2. 拼接操作 ⊕字符串直接连接,如 "low" ⊕ "er" = "lower"。
    u1⊕u2=loweru_1 \oplus u_2 = \text{lower}
  3. 还原结果 w拼接后剔除词边界标记,得到与原词完全一致的单词,证明 BPE 可逆。
    w=lowerw = \text{lower}

预训练模型

乐园要办超级城堡展,几十家参展商共用一套零件目录。游客再多、工期再紧,大家都能按统一标准生产,任意订单都不会因“缺零件”卡壳。GPT、BERT 这些大模型,就是城堡展的参展商。

GPT 系列使用 Byte-level BPE:从字节级开始建词表,固定词表大小 50,257,任何语言、任何符号(包括 emoji)都能切分。BERT 使用的是 BPE 的变体 WordPiece,词表约 3 万。Hugging Face 的 tokenizers 库把这些算法工程化,提供现成的 ByteLevelBPETokenizer 等组件,Tokenizer 生态由此成为预训练管线的标准一环。多语言混合文本(如中英混排的新闻、代码与注释混合的文件)也能被统一词表处理,不再需要每种语言各自造词表。

统一零件目录让整个乐园高效运转——统一词表让所有预训练任务复用同一套 BPE 模具,这正是 GPT 与 BERT 能处理无限多样文本的共同基石。

s→BPE(u1,u2,…,uk)→Embed{e1,…,ek}s \xrightarrow{\text{BPE}} (u_1, u_2, \dots, u_k) \xrightarrow{\text{Embed}} \{\mathbf{e}_1, \dots, \mathbf{e}_k\}
一条文本先被 BPE 切成词元序列,再通过查表得到每个词元的稠密向量,这些向量才是模型真正“看见”的内容。
  1. 输入句子 s原始文本,未经任何修改的字符串。
    s="the lowest price"s = \text{"the lowest price"}
  2. BPE 切分把句子映射为词元序列,例如拆分出 "the"、"low"、"est" 等词元。
    s↦(u1,u2,…,uk)s \mapsto (u_1, u_2, \dots, u_k)
  3. 嵌入向量 e_i每个词元通过查表映射为 d 维稠密向量,送入神经网络继续处理。
    ui↦ei∈Rdu_i \mapsto \mathbf{e}_i \in \mathbb{R}^{d}

改进变体

隔壁积木厂觉得“光看销量”太粗放,推出了自己的决策标准;还有工厂干脆不做预切割,把整块板材直接送进车间。BPE 家族由此开枝散叶,衍生出多个改进版本。

WordPiece(BERT 采用)换了一种选择标准:不再看组合的绝对频次,而是看“绑定程度”,选择分数最高的对合并。Unigram(T5 等模型可选)则反过来做——先给出一个很大的候选词表,再用 EM 算法迭代剪枝,每步去掉对语言模型损失贡献最小的词元。SentencePiece 更激进:不做预分词,直接把整句(含空格)作为字符流,用特殊符号标记空格,天然支持中文、日语等无空格语言。它们各有取舍:BPE 简单可控,WordPiece 更讲究绑定关系,Unigram 词表质量高但训练更昂贵。

光看销量会误判:超高频的 “o“ 和 ”t“ 从不并肩出现,WordPiece 的比值打分体现了”高频共现“与”真正绑定”之间微妙的区别。

score(a,b)=f(ab)f(a)⋅f(b)\text{score}(a, b) = \frac{f(ab)}{f(a) \cdot f(b)}
WordPiece 的合并分数 = 组合共现频次 ÷ 两个词元各自频次的乘积。比值越高,说明二者绑定越紧密,越值得优先合并。
  1. 共现频次 f(ab)词元 a 与 b 拼接后(即组合 ab)在语料中出现的总次数。
    f(ab)=count(a 后紧跟 b)f(ab) = \text{count}(a \text{ 后紧跟 } b)
  2. 独立频次乘积分母惩罚“各自都超高频”的组合——比如 “t“ 和 ”h” 单看都很多,但未必总在一起。
    f(a)⋅f(b)f(a) \cdot f(b)
  3. 比值决策分数越高说明绑定越紧密,优先合并;直观理解就是“不是卖得多,而是绑得紧”。
    score(a,b)=f(ab)f(a)⋅f(b)\text{score}(a, b) = \frac{f(ab)}{f(a) \cdot f(b)}

实际应用

预制件方案从城堡车间推广到主题酒店、机器人餐厅、游客纪念品店,整个乐园的供应链都围绕同一套零件目录运转。应用越广,BPE 的价值越凸显。

在机器翻译中,低资源语言(如斯瓦希里语)语料稀缺,词级分词覆盖率极差,BPE 子词让翻译模型依然能拼出绝大部分词汇。在多语言混合场景下,一套共享词表同时服务中英日阿多种语言,避免每种语言独立建表的资源浪费。在代码生成模型中,代码是自然语言、变量名、符号的混合体,BPE 天然拆解 "camelCase"、"snake_case" 这类复合词,显著提升代码补全质量。实际部署中,工程师常用压缩率来评估词表质量——分词后序列越短,说明子词切分越合理。

从单一车间到全乐园供应链,“高频复用”的思想穿透了所有生产环节。BPE 也一样——从机器翻译到代码模型,它始终是文本进入大模型前的第一道、也最关键的一道工序。

r=NcharNtokenr = \frac{N_{\text{char}}}{N_{\text{token}}}
压缩率 = 原始字符总数 ÷ 分词后的词元总数。压缩率越大于 1,说明 BPE 把字符压缩成了更少的子词单元,词表越高效。
  1. 字符总数 N_char分词前语料的字符(或字节)总数,代表“散装颗粒”的原始数量。
    Nchar=语料中所有字符数N_{\text{char}} = \text{语料中所有字符数}
  2. 词元总数 N_token分词后的词元数,也就是模型实际要处理的序列长度。
    Ntoken=编码后的词元数量N_{\text{token}} = \text{编码后的词元数量}
  3. 压缩率 r大于 1 说明子词起到了压缩序列的作用;压缩率越高,训练与推理的效率越高。
    r=NcharNtokenr = \frac{N_{\text{char}}}{N_{\text{token}}}

AI 应用场景

多语言机器翻译的分词预处理

阶段:数据预处理 / Tokenization

解决的问题:传统词级分词在低资源语言上词表覆盖不足,OOV 高频出现,翻译质量大打折扣。BPE 子词在字符层面兜底,任何拼写组合都能被切分,让共享词表同时覆盖多种书写系统。

具体案例:一个多语言翻译系统用 SentencePiece + BPE 在一批混合语料上训练出共享子词词表,同一词表同时服务中文、英语、阿拉伯语,词表体积比语言独立建表缩小约 60%,低资源语言对的 BLEU 提升显著。这就像乐高工厂为整个乐园供一套通用零件目录,而不是每个园区各建一座仓库。

大模型 Tokenizer 训练与选型

阶段:预训练前的文本预处理

解决的问题:GPT、BERT、Llama 都需要固定大小的词表,直接用词级切分会导致词表爆炸或 OOV 频繁。BPE 将词表大小与合并轮数解耦,让工程师能精准控制“模具预算”。

具体案例:预训练团队用 Hugging Face tokenizers 库在 50GB 多语言语料上训练 ByteLevelBPETokenizer,词表设为 50,257;训练时用 OOV 率与压缩率两个指标评估,调整合并轮数后,下游任务的训练吞吐提升了约 15%。这套评估流程和乐高工厂用“缺货率 + 组装时间”衡量模具方案如出一辙。

代码生成模型的混合文本处理

阶段:数据清洗 / 分词

解决的问题:代码文件是“自然语言 + 变量名 + 符号”的混合体,词级切分对 "getUserById"、"learning_rate" 这类复合词无能为力;BPE 子词能自然拆解它们,让模型跨语言(代码 + 注释)统一建模。

具体案例:CodeLlama 使用 byte-level BPE 分词,变量名 “getUserById“ 被拆成 ”get”、"User"、"By"、“Id“ 等已知子词,代码补全的准确率因此明显优于按词或按字符的 baseline。这与预制件工厂用同一套零件拼装”城堡“和”机器人”是同一个道理。

Python 演示

python45 行
from collections import Counter  def get_pair_stats(vocab):    pairs = Counter()    for word, freq in vocab.items():        symbols = word.split()        for i in range(len(symbols) - 1):            pairs[symbols[i], symbols[i + 1]] += freq    return pairs  def merge_pair(pair, vocab):    bigram = ' '.join(pair)    merged = ''.join(pair)    out = {}    for word, freq in vocab.items():        out[word.replace(bigram, merged)] = freq    return out  def train_bpe(corpus, num_merges):    vocab = {}    for word, freq in corpus:        vocab[' '.join(list(word)) + ' </w>'] = freq    merges = []    for _ in range(num_merges):        pairs = get_pair_stats(vocab)        if not pairs:            break        best = max(pairs, key=pairs.get)        merges.append(best)        vocab = merge_pair(best, vocab)    return merges, vocab  if __name__ == '__main__':    corpus = [('low', 5), ('lower', 2), ('newest', 6), ('widest', 3)]    merges, vocab = train_bpe(corpus, 8)    print('Learned merge rules:')    for i, m in enumerate(merges, 1):        print('Round %d: %s -> %s' % (i, ' '.join(m), ''.join(m)))    print('Final vocab (%d entries):' % len(vocab))    for w in sorted(vocab):        print(' ', w)
目的:用约 30 行核心逻辑从零实现 BPE 训练,在 low/lower/newest/widest 小语料上迭代合并,输出每一步的合并规则与最终词表,直观展示“最高频字符对反复合并”的完整过程。
  1. vocab[' '.join(list(word)) + ' </w>'] = freq初始化:把每个词拆成带空格的字符序列并追加词尾标记,比如 "l o w </w>"
  2. pairs[symbols[i], symbols[i + 1]] += freq统计相邻字符对时按词频加权,"l o" 在 low、lower 各出现一次,共计数 7
  3. best = max(pairs, key=pairs.get)从所有相邻对中选出频次最高的那对,等价于公式里的 argmax
  4. word.replace(bigram, merged)把词中所有 “e s“ 替换为合并后的词元 ”es”,完成一次合并
  5. merges.append(best)把本轮合并规则记录下来,这份规则表就是编码和解码共用的“模具清单”

常见误区

误区反正合并能压缩文本、提升覆盖,那就多合并几千轮,词表越大覆盖越全,模型效果一定越好。

正解词表大小 = 初始字符数 + 合并轮数,合并越多词表越大,Embedding 层和输出 Softmax 的内存与算力开销都会上升;同时超大词表会稀释每个词元的训练频次,低频词元反而学不好。工业界通常控制在 32k 到 250k 之间。模具库不是越大越好——每副模具都占仓库储位,还要定期维护。

为何常见:“覆盖越全越好”的直觉很自然,但忽略了工程上存储与统计稀疏性的代价。

误区BPE 把 "un"、"happy"、"ness" 合并出来,说明它懂得词根和构词法,子词就是有语义的词素。

正解BPE 完全基于频次统计,只做无损压缩,不理解任何语义。它合并出的子词如 "est"、“lo“ 只是高频共现的形式组合,未必对应语言学的词根。真正的语义来自后续语言模型的训练,而不是分词阶段。乐高工厂把”窗+框”铸成预制件,是因为卖得好,而不是因为它懂建筑。

为何常见:人看到有意义的子词会本能投射语义,误以为算法也有这种理解。

误区教程里全是英文例子,BPE 从字母开始合并,中文没有空格,肯定用不了。

正解BPE 可以从字节(byte-level)开始,GPT 正是用 byte-level BPE 覆盖全部 Unicode——中文、日文、emoji 都能处理;也可以在粗分词(按空格和标点粗略切分)后的词元上运行。中文即使不做预分词,SentencePiece 方案也能直接处理。

为何常见:英文语料的教学示例太普遍,让人误以为算法绑定拉丁字母。

误区分词把句子变成一串词元 id,看上去像“翻译”了一遍,解码肯定是猜不回去的。

正解BPE 是无损的——解码就是按顺序拼接子词并剔除边界标记,能完整还原原词与顺序,字节级 BPE 连大小写和空格都能复原。真正丢失原始信息的是分词之后的模型编码过程,而不是 BPE 本身。

为何常见:把“分词”和“语义编码”两个阶段混为一谈,误解了 BPE 在管线中的位置。

面试题

Q1. BPE 每一轮迭代合并的对象是什么?

单选题 · easy

  • A.出现次数最高的单个字符
  • B.出现次数最高的相邻字符对← 正确答案
  • C.出现次数最低的字符对
  • D.随机选取的字符对

答案:B。BPE 的核心操作是统计相邻字符对的共现频次,把最高频的那对合并成一个新词元,就像乐高工厂只给最畅销的组合开模具。A 是单个字符而非字符对;C、D 与“最高频合并”的原则相悖。

Q2. BPE 主要解决 NLP 中的什么问题?

单选题 · easy

  • A.模型训练速度过慢
  • B.词表过大与未登录词← 正确答案
  • C.文本编码乱码问题
  • D.数据集标注不足

答案:B。BPE 在词级和字符级之间取平衡,用子词词表同时缓解词表规模爆炸和 OOV(未登录词)问题。它不负责训练加速、字符编码或数据标注。

Q3. 初始字符集大小为 100,执行 200 次合并后词表大小是多少?

单选题 · easy

  • A.100
  • B.200
  • C.300← 正确答案
  • D.20000

答案:C。词表大小 = 初始字符数 + 合并轮数,即 100 + 200 = 300。每次合并只新增一个词元,不会成倍增长,这正体现了 BPE 词表规模的可控性。

Q4. BPE 的解码过程是?

单选题 · mid

  • A.按最长匹配拆分字符串
  • B.将词元直接拼接还原← 正确答案
  • C.用语言模型预测还原
  • D.按空格分割还原

答案:B。解码就是把词元 id 查回字符串、按序拼接并剔除边界标记,过程无损可逆。A 是编码时的贪心最长匹配;C 违反了 BPE 的确定性;D 是词级分词的做法。

Q5. 以下哪个不是子词分词算法?

单选题 · easy

  • A.WordPiece 子词分词
  • B.Unigram 子词分词
  • C.SentencePiece 子词分词
  • D.TF-IDF 文本统计← 正确答案

答案:D。WordPiece、Unigram、SentencePiece 都是子词分词家族成员,分别从不同角度改进 BPE;TF-IDF 是文本加权统计方法,用于关键词提取而非分词。

Q6. 关于 WordPiece 与 BPE 的选择标准,正确的是?

单选题 · mid

  • A.WordPiece 只看组合频率
  • B.BPE 看频率的比值
  • C.WordPiece 看频率的比值← 正确答案
  • D.两者的标准完全相同

答案:C。BPE 直接选最高频字符对;WordPiece 用 f(ab)/(f(a)f(b)) 的比值衡量“绑定程度”,避免被各自超高频但从不共现的字符误导。可以理解为 BPE 看销量,WordPiece 看“绑定紧密度”。

Q7. BPE 的优势有哪些?

多选题 · mid

  • A.能处理未登录词← 正确答案
  • B.支持多语言混合文本← 正确答案
  • C.压缩词表规模← 正确答案
  • D.理解词语的语义

答案:ABC。BPE 用子词切分兜底,任何生词都能拆到字符级,因此能处理未登录词;字节级 BPE 覆盖全部 Unicode,天然支持多语言混合;词表大小由合并轮数控制,远小于词级词表。BPE 是纯统计压缩,不理解语义,故 D 错误。

Q8. BPE 每轮迭代包含哪些步骤?

多选题 · mid

  • A.统计候选对的频次← 正确答案
  • B.选出最高频的字符对← 正确答案
  • C.合并并更新整个语料← 正确答案
  • D.按语义切分每个句子

答案:ABC。每轮流程是“统计相邻对频次 → argmax 选最高频对 → 合并替换并更新语料”,循环直到轮数耗尽。BPE 完全不涉及语义分析,所以 D 错误。

Q9. 关于 BPE 与未见词的关系,以下说法正确的是?

单选题 · hard

  • A.合并轮数越多词表越小
  • B.任意生词都能被切分编码← 正确答案
  • C.未见词完全无法编码
  • D.词表必须覆盖全部字符

答案:B。BPE 编码时从左到右贪心匹配,优先级是长词元 > 短词元 > 单字符,最终一定能拆到字符级兜底,所以任何生词都能编码。A 说反了,合并越多词表越大;C、D 与字符兜底机制相矛盾。

Q10. 关于 Byte-level BPE(GPT 采用的变体),正确的是?

单选题 · mid

  • A.从字节序列而非字符开始统计← 正确答案
  • B.只能处理英文等拉丁文本
  • C.词表必须包含完整单词
  • D.无法编码任意 Unicode 字符

答案:A。Byte-level BPE 把文本先编码为 UTF-8 字节,再对字节序列做合并,因此能覆盖任意 Unicode 字符、emoji 和多语言文本;词表无须包含完整单词。B、C、D 都与字节级设计相矛盾。