想象你正面对一箱散装的乐高颗粒。要拼出一个“城堡”单词,你得一片一片地找到 l、o、w 三颗颗粒;要拼十次“城堡”,就得重复十次这样的翻找动作。乐高工厂的设计师发现,很多图纸里“l+o+w“这个组合反复出现,于是他们提前把这三颗颗粒预拼成一个标准组件,写进零件目录。下次任何人需要”城堡“这个词,直接拿一个组件即可。GPT 系列的分词器,就是这样一个”乐高组件目录设计师”。它叫 BPE(Byte Pair Encoding,字节对编码),原本是 1994 年用于压缩数据的算法,2016 年被引入自然语言处理,至今仍是 GPT-2、GPT-3、GPT-4 等大模型切分文本的幕后功臣。本篇将用乐高的语言,拆解 BPE 如何把海量文本变成一套精巧的子词组件。

岗位关联

掌握 BPE 是理解 GPT 如何“看”文本的第一块基石。无论你做数据清洗、模型微调还是推理优化,分词质量都直接决定模型效果与算力成本——这是每位 AI 工程师都无法绕开的必修课。

目录
  1. 可视化演示
  2. 一、BPE核心原理
  3. 二、词汇表构建
  4. 三、编码解码流程
  5. 四、GPT系列实现
  6. 五、算法对比
  7. 六、权衡与优化
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示BPE合并过程、词汇表增长曲线与三种分词算法对比,支持步进式探索子词切分核心机制。

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

BPE合并过程 从字符级别开始统计相邻字符对频率 合并最高频对生成新子词单元 |V| = |V_chars| + N_merges 反复合并直到达到目标词汇表大小

一、BPE核心原理

乐高工厂每天收到成千上万张拼装图纸,小乐发现“车轮+车轴”这对组合在图纸里反复出现。与其让工人们每次都从零找颗粒,不如先把这对颗粒预拼成一个标准组件。BPE 算法的思路与此完全一致:它把文本看作一排字符积木,统计哪两个相邻的字符“总是黏在一起”,就把它们合并成一个子词积木——这个过程就是“字节对合并”。

1994 年,BPE 诞生于数据压缩领域,工程师用它压缩二进制文件中的重复模式。2016 年,NLP 研究者 Sennrich 等人发现同样的思路可以压缩“词表”:与其让词表装下所有单词,不如让高频字符对一步步合并成子词。GPT 系列正是沿用了这一思路,将 BPE 作为默认分词算法。

具体流程分四步。第一步,把语料切碎成单个字符,相当于把所有乐高颗粒拆到最细;第二步,扫描所有相邻字符对,统计每对出现的频率;第三步,挑出频率最高的一对,合并成一个新的子词;第四步,重复第二步和第三步,直到词表达到预定大小或没有可合并的对为止。

回到乐高工厂,小乐用这套流程优化了生产线:图纸上“车轮+车轴”出现频率最高,那就先预拼它;下次再出现“车轮车轴+车厢”,再预拼成更大的组件。BPE 的本质,就是让数据自己说话——高频组合永远优先获得合并的资格。

freq(x,y)=∑i=1N−11[si=x, si+1=y]\displaystyle \text{freq}(x, y) = \sum_{i=1}^{N-1} \mathbb{1}[s_i = x,\ s_{i+1} = y]
这个公式统计的是:在整个文本序列中,字符 x 后面紧跟着字符 y 这个组合一共出现了多少次。出现次数最多的相邻对,就是下一个要被乐高工厂预拼的组件。
  1. 相邻字符对文本中位置紧挨的两个字符构成一对组合,我们关心的是目标组合 (x, y)
    (si, si+1)(s_i,\ s_{i+1})
  2. 指示函数当这个相邻对恰好等于 (x, y) 时记 1,否则记 0,相当于一个“是否符合条件”的开关
    1[si=x, si+1=y]∈{0, 1}\mathbb{1}[s_i = x,\ s_{i+1} = y] \in \{0,\ 1\}
  3. 求和汇总从位置 1 扫到 N-1,把所有命中次数累加起来,得到该字符对在语料中的总频次
    ∑i=1N−11[si=x, si+1=y]=count(x,y)\sum_{i=1}^{N-1} \mathbb{1}[s_i = x,\ s_{i+1} = y] = \text{count}(x, y)

二、词汇表构建

乐高工厂的零件目录不是凭空设计的。小乐先统计所有图纸中出现的每一种基础颗粒,把它们登记在册;然后按 BPE 规则把高频对预拼成新组件,每预拼一个,目录就多一个条目。目录的初始版本很简单:语料中出现过的所有独立字符,比如英文的 26 个字母加上标点符号,这就是“初始字符表”。

接下来,每次合并都会为目录增加一个全新的子词条目。比如从“low“和”lower“中,先合并出”lo“,再合并出”low“,继而合并出”lower“。每完成一次合并,词汇表的容量就加一。这个”合并规则”会被记录下来,成为之后切分新文本的依据。

这里有一个关键的“子词粒度”概念:合并次数越多,子词越长,粒度越粗。如果合并到极致,整个高频单词会成为一个独立组件;如果一次都不合并,则退化为纯字符级切分。实际使用中,我们通常预设一个目标词表大小(比如 GPT-2 的 50257),到点即停。

这就像乐高目录从最初的几十种基础颗粒,慢慢扩充到包含各种预拼组件的厚厚一本。目录太厚翻起来费劲(词表过大),太薄又什么都拼不出来(词表过小)——构建词汇表的过程,就是在寻找那个刚刚好的平衡点。

∣Vfinal∣=∣Vinit∣+T\displaystyle |V_{\text{final}}| = |V_{\text{init}}| + T
最终词汇表的大小等于初始字符数加上合并次数 T。如果你希望词表有 5 万个子词,而初始字符有 260 个,那就需要执行约 49740 次合并。
  1. 初始词汇表语料中所有独立字符的集合,是目录的第一版
    Vinit={c∣c 出现在语料中}V_{\text{init}} = \{c \mid c \text{ 出现在语料中}\}
  2. 每次合并选定最高频字符对并合并成一个新子词,目录条目加一
    ∣Vt+1∣=∣Vt∣+1|V_{t+1}| = |V_t| + 1
  3. T 次迭代经过 T 轮合并后,最终词表大小恰好等于初始字符数加合并次数
    ∣Vfinal∣=∣Vinit∣+T|V_{\text{final}}| = |V_{\text{init}}| + T

三、编码解码流程

有了零件目录,接下来就是拼装与拆解的问题了。拼装环节,工人拿到一个单词,会先看目录里有没有现成的组件:整个单词有,直接拿;没有,就拆成目录中能匹配的最大子词组合。拆解环节则简单得多,把组件按顺序拼回去就行,不需要任何额外规则。

训练阶段是整个流程的地基。在训练时,算法在大量语料上执行合并操作,学出一套“合并规则”和最终的子词词汇表。这个阶段结束后,词汇表和规则就冻结了,进入编码阶段。

编码时采用“贪心最长匹配”策略:从左到右扫描文本,每次都尝试用词表中最长的子词去匹配当前位置。比如“lower“如果词表里有”low“和”er”,就切分成 low + er,而不是 l + o + w + e + r。解码则完全相反——把每个子词直接拼接起来,原文本就回来了,不需要任何语言模型参与。

至于“未知词处理”,乐高工厂也有对策:遇到目录里完全不存在的单词,BPE 会一直向细粒度拆解,直到拆成单个字符——如果语料里有这个字符,就能拼出来;极端情况甚至拆到字节级别,几乎不会出现“完全拼不出来”的窘境。

encode(s)=[v1,v2,…,vk]且v1⊕v2⊕⋯⊕vk=s\displaystyle \text{encode}(s) = [v_1, v_2, \dots, v_k] \quad \text{且} \quad v_1 \oplus v_2 \oplus \cdots \oplus v_k = s
编码把一个字符串拆成一串子词,解码则把这串子词首尾拼接还原。两者互为逆操作,中间没有任何信息丢失。
  1. 切分映射把原文 s 按照词表切分,得到一个子词序列 v₁ 到 v_k,这就是编码结果
    s↦[v1,v2,…,vk]s \mapsto [v_1, v_2, \dots, v_k]
  2. 拼接还原把所有子词按顺序拼接,符号 ⊕ 表示字符串连接,结果恰好等于原文 s
    v1⊕v2⊕⋯⊕vk=sv_1 \oplus v_2 \oplus \cdots \oplus v_k = s
  3. 信息守恒由于每个子词都是原文本的连续片段,拼接不增不减,所以解码永远无损
    decode(encode(s))=s\text{decode}(\text{encode}(s)) = s

四、GPT系列实现

乐高在不同国家卖的颗粒形状其实是有差异的,这给全球拼装带来了麻烦。GPT 系列也面临类似问题:用英文字母作为基础颗粒,中文、日文、阿拉伯文怎么办?GPT-2 的答案是“字节级 BPE”——干脆统一用全球通用的“标准颗粒”:UTF-8 字节。

所谓字节级 BPE,就是先把任何语言的文本编码成 UTF-8 字节序列,然后在这些字节(取值范围 0 到 255)上执行 BPE 合并。这样一来,无论中文的“你”还是英文的“a“,都先变成若干个字节,再在字节层面学习子词。初始词汇表从”所有字符“变为”所有字节”,大小固定为 256,完美覆盖任意语言。

GPT-2 论文中报告的词汇表大小为 50257,其中 256 个是基础字节,另外约 5 万个是通过 BPE 合并得到的子词。GPT-3 延续了 GPT-2 的字节级 BPE 方案,只在词表细节上做了微调;GPT-4 虽然细节未完全公开,但业界普遍认为其分词器同样基于字节级 BPE 的变体。这一设计的核心优势是:无论输入什么语言、什么符号,都能被编码为已知字节,从根上解决了未登录词问题。

从此,乐高图纸不再区分“英文版”还是“中文版”,全球统一用字节颗粒拼装。这正是 GPT 系列能流畅处理上百种语言的分词层秘密。

UTF-8(t)=b1b2…bn,bi∈{0,1}8\displaystyle \text{UTF-8}(t) = b_1 b_2 \dots b_n, \quad b_i \in \{0, 1\}^8
任意字符 t 先被转换成 1 到 4 个字节,每个字节都是 0 到 255 之间的整数。BPE 就在这些字节上做合并,相当于乐高全球统一了基础颗粒规格。
  1. 字符转字节任意 UTF-8 字符被编码为长度 1 到 4 的字节序列
    t↦(b1,b2,…,bn)t \mapsto (b_1, b_2, \dots, b_n)
  2. 字节范围每个字节 bᵢ 的取值是 0 到 255,共 256 种可能
    bi∈{0,1,…,255}b_i \in \{0, 1, \dots, 255\}
  3. 字节当字符把这 256 种字节当作“初始字符表”,BPE 在字节序列上执行合并
    ∣Vinit∣=256|V_{\text{init}}| = 256

五、算法对比

市面上的积木品牌不止乐高一家,美高、杂牌积木各有各的拼装逻辑。在子词切分领域,BPE 并非唯一选择,它的两个著名“竞品”是 WordPiece 和 SentencePiece。理解它们之间的差异,能帮你更清楚地认识 BPE 的个性。

WordPiece 是 BERT 系列采用的分词算法。它与 BPE 最大的不同在于合并依据:BPE 只看频率——出现最多的对就合并;WordPiece 则看“概率比”——两个字符经常一起出现,且不是偶然的,才值得合并。用公式表达,WordPiece 会给每个候选对算一个得分,得分高者优先。

SentencePiece 则是另一条路线:它由谷歌开源,特点是先把文本中所有空格也当作普通字符参与合并。这样分词结果天然可逆,不需要“在词之间补空格”的后处理,尤其适合日语等没有空格的语言。此外,还有更粗粒度的“词级切分”(整个单词一个 token)和更细粒度的“字符级切分”(每个字符一个 token),分别对应乐高的大组件和散颗粒——前者词表容易爆炸,后者序列太长,BPE 的子词方案正好站在两者之间。

score(x,y)=freq(xy)freq(x)⋅freq(y)\displaystyle \text{score}(x, y) = \frac{\text{freq}(xy)}{\text{freq}(x) \cdot \text{freq}(y)}
分子是 xy 同时出现的次数,分母是 x 和 y 各自出现的次数相乘。如果这个比值很大,说明 x 和 y 的共现远超偶然水平,应该合并。
  1. 联合频率分子统计 xy 作为一个相邻对在语料中的出现次数
    freq(xy)\text{freq}(xy)
  2. 边缘频率乘积分母是 x 单独出现的次数乘以 y 单独出现的次数,起归一化作用
    freq(x)⋅freq(y)\text{freq}(x) \cdot \text{freq}(y)
  3. 得分判定得分越高的字符对,共现越“超出偶然”,优先合并;BPE 没有这层归一化,只看原始频率
    score(x,y)≫1⇒合并\text{score}(x, y) \gg 1 \Rightarrow \text{合并}

六、权衡与优化

乐高目录如果收录了十万种组件,翻起来费时费力,工厂仓库也放不下;如果只有几十种基础颗粒,拼一座城堡又要反复拼装。BPE 的词汇表大小正是这样的权衡问题,它直接影响两个关键指标:序列长度和模型参数规模。

词汇表越大,单个子词携带的信息越多,一句话被切成的 token 数越少,序列就越短。但代价是嵌入层(embedding layer)的参数规模跟着膨胀:词表从 3 万扩到 6 万,嵌入矩阵的行数就翻倍,显存占用直线上升。反之,词汇表越小,模型参数少,但序列变长,Transformer 的计算量随序列长度平方增长,训练和推理都会变慢。

实践中常用“压缩比”来衡量分词效率:原始字符数除以子词数。GPT-2 的 50257 词表对英文的压缩比大约在 3 到 5 之间,意味着平均每个 token 能表示 3 到 5 个字符。这个数字不是越大越好——它要和嵌入层开销、多语言覆盖度、模型容量放在一起综合判断。

在“数据为中心 AI 范式”下,分词是数据质量评估的第一道关口。高质量的分词器能忠实保留语料中的语义单元,让模型用更少的 token 理解更多的信息;而糟糕的分词器会把数据切得支离破碎,即使后续模型再强大,也难以从破碎的输入中恢复语义——这正是“垃圾进,垃圾出”在分词层的体现。

r=L字符L子词\displaystyle r = \frac{L_{\text{字符}}}{L_{\text{子词}}}
压缩比 r 表示每个子词平均覆盖多少字符。r 太小说明子词拆分过细,序列过长;r 太大则意味着词表可能过于庞大。
  1. 字符总数原始文本的字符数量,是压缩的基准
    L字符L_{\text{字符}}
  2. 子词总数经过 BPE 切分后得到的 token 数量
    L子词L_{\text{子词}}
  3. 比值含义两者相除,r 大于 1 表示有压缩效果,r 越大单 token 信息密度越高
    r=L字符L子词>1r = \frac{L_{\text{字符}}}{L_{\text{子词}}} > 1

AI 应用场景

多语言数据统一分词

阶段:数据清洗与预处理

解决的问题:传统按空格和词法切分在多语言语料上捉襟见肘——中文没有空格,日语词形多变,阿拉伯文有复杂的词缀。用字节级 BPE,所有语言先统一转成 UTF-8 字节,再合并出跨语言的子词,一套词表通吃。

具体案例:某跨境电商平台收集了中、英、日、西四国用户评论,此前分别维护四套分词规则,模型多语言评测 F1 仅 0.71。改用字节级 BPE 统一分词后,词表共享率提升,F1 升至 0.83,训练数据利用率显著提高。

垂直领域词表定制

阶段:模型训练前的 Tokenizer 训练

解决的问题:通用 BPE 词表在垂直领域覆盖不足——医学术语、法律条文、代码变量名中的高频组合,在通用语料里可能从未出现过,导致序列被切得零碎。

具体案例:某医疗 AI 公司用 20 万份电子病历训练专属 BPE 词表,将“高血压”“心律失常”等专业术语合并为单个 token。微调后的模型在医疗 NER 任务上 F1 提升 5.2 个百分点,推理速度也因序列缩短而加快。

推理成本优化

阶段:模型部署与推理优化

解决的问题:Transformer 的计算量与序列长度平方成正比,序列每缩短 10%,推理成本就明显下降。BPE 的压缩能力直接转化为 GPU 算力的节省。

具体案例:某大模型服务商在接入长文档问答功能时,通过重新训练 BPE 词表,将平均序列长度从 4120 token 压缩到 3570 token,响应延迟降低约 24%,在保持答案质量不变的前提下,把每百万 token 的服务成本压低了近三成。

Python 演示

python47 行
from collections import Counter  def bpe_train(corpus, num_merges):    """训练BPE,返回最终词汇表和合并规则列表。"""    # 初始词汇表:语料中所有独立字符    vocab = set(''.join(corpus))    # 每个词切成字符序列,末尾加结尾标记    words = [list(w) + ['</w>'] for w in corpus]    merges = []     for step in range(num_merges):        # 统计所有相邻字符对的出现次数        pairs = Counter()        for word in words:            for i in range(len(word) - 1):                pairs[(word[i], word[i + 1])] += 1        if not pairs:            break         # 找出频率最高的相邻对        best = max(pairs, key=pairs.get)        merges.append(best)         # 将语料中所有该字符对合并成一个新子词        new_words = []        for word in words:            merged, i = [], 0            while i < len(word):                if i < len(word) - 1 and word[i] == best[0] and word[i + 1] == best[1]:                    merged.append(best[0] + best[1])                    i += 2                else:                    merged.append(word[i])                    i += 1            new_words.append(merged)        words = new_words        vocab.add(best[0] + best[1])        print(f'第{step + 1}次合并:{best[0]} + {best[1]} -> {best[0] + best[1]}')     return vocab, merges  corpus = ['low', 'lower', 'lowest', 'newer']vocab, merges = bpe_train(corpus, 5)print('最终词汇表:', sorted(vocab))print('合并规则:', merges)
目的:用一个小型英文语料完整演示 BPE 的训练过程——从统计相邻字符对频率,到逐轮合并最高频对,最终得到子词词汇表和合并规则。
  1. pairs[(word[i], word[i + 1])] += 1用 Counter 统计所有相邻字符对的共现次数,这就是 BPE 的“频率统计”环节
  2. best = max(pairs, key=pairs.get)从所有相邻对中选出出现次数最高的那一个,作为本轮合并对象
  3. merged.append(best[0] + best[1])把两个字符拼接成一个新的子词字符串,例如 'l' + 'o' 得到 'lo'
  4. i += 2合并成功后跳过两个字符,避免同一个字符被重复合并
  5. vocab.add(best[0] + best[1])每合并一次就把新子词加入词汇表,词表容量随之加一
  6. words = new_words用合并后的序列替换旧序列,下一轮统计基于最新的分词状态

常见误区

误区我以为 BPE 每次迭代就是数一数哪个字符出现最多,比如语料里 'e' 最多,就先把 'e' 合并掉。

正解BPE 统计的是“相邻字符对”的频率,不是单个字符的频率。它看的是 x 和 y 紧挨着出现的次数,比如 'l' 和 'o' 总是一起出现才合并成 'lo'。单个字符出现再多,只要没有固定搭档,就不会被合并。

为何常见:因为算法名字叫“字节对编码”,直觉上容易理解为“对单字节编码”,忽略了核心操作对象是“相邻的一对”。

误区词表越大,能表示的子词就越多,模型的理解能力一定越强,所以训练时把词表设得越大越好。

正解词表增大会同时带来三个代价:嵌入层参数成倍膨胀、显存占用上升、训练样本的稀疏性加剧。而且词表大到一定程度后,新加入的多是低频长尾子词,对压缩比贡献微乎其微。GPT-2 用 5 万左右的词表,是权衡后的选择。

为何常见:人们习惯性地认为“能力与规模正相关”,但忽略了词表带来的参数成本和收益递减规律。

误区用了 BPE 之后,任何生词都能被切分,所以未登录词问题被彻底消灭了。

正解BPE 只是把未登录词的粒度从“词”降到了“子词或字符”。单词级的 OOV 问题确实大幅缓解,但如果一个词里的字符在训练语料中从未出现(比如某些生僻汉字),拆到字符级还是会失败。字节级 BPE 进一步把兜底层降到 256 种字节,几乎不会失败,但严格说仍依赖 UTF-8 编码覆盖。

为何常见:看到 BPE 能拆英文生词,就想当然地认为它的覆盖范围是无限的,忽略了“兜底单元”本身也有边界。

误区BERT 用的 WordPiece 和 GPT 用的 BPE 不都是合并高频字符对吗?我觉得它们完全一样。

正解两者虽然都迭代合并子词,但筛选标准不同。BPE 只看原始频率,谁出现次数多就合并谁;WordPiece 用概率比(互信息思想)衡量共现是否超出偶然水平。结果上,WordPiece 更倾向于合并“有强绑定关系”的对,BPE 更偏保守地跟随频率分布。

为何常见:两者的训练流程看起来很相似,都是“统计-合并-重复”的循环,容易被表面流程迷惑,忽略了合并依据的差异。

误区分词就是把文本切一切,对模型最终效果影响不大,随便选个 tokenizer 就行。

正解在数据为中心 AI 范式中,分词是数据质量的第一道闸门。切分粒度直接影响序列长度、信息密度和语义完整性——同一句话用不同的词表切分,模型看到的 token 序列完全不同,训练效率和下游任务表现都会受牵连。

为何常见:因为分词发生在“数据进入模型之前”,它的影响是间接的,容易被从业者低估。

面试题

Q1. BPE 算法每次迭代会合并哪一对字符?

单选题 · easy

  • A.随机挑选的一对相邻字符
  • B.语料中出现频次最高的相邻对← 正确答案
  • C.字典序排在最前面的字符对
  • D.在文本中首次出现的相邻对

答案:B。BPE 的核心规则就是“谁高频,谁先合并”。就像乐高工厂优先预拼最常出现在图纸里的组件一样,BPE 统计所有相邻字符对的出现次数,每轮选出频次最高者合并。随机、按字典序、按首次出现的位置都不是 BPE 的策略。

Q2. BPE 训练开始时,初始词汇表包含什么?

单选题 · easy

  • A.语料中所有出现过的完整单词
  • B.语料中所有独立的字符单元← 正确答案
  • C.从外部词典挑选的部分单词
  • D.人工指定的若干字符组合

答案:B。BPE 的训练起点是“拆碎到不能再碎”——语料中所有独立字符构成初始词汇表,相当于乐高目录的初版只收录最基础颗粒。完整单词、外部词典、人工字符组合都是后续合并阶段才出现的东西。

Q3. GPT-2 使用的字节级 BPE 与经典 BPE 的关键区别是什么?

单选题 · mid

  • A.基础单元从字符换成 UTF-8 字节← 正确答案
  • B.合并规则变成随机采样过程
  • C.不再统计字符对出现频率
  • D.词汇表必须包含完整单词

答案:A。经典 BPE 以字符(如字母)为最小单元,遇到生僻字符会失效;GPT-2 把所有文本先编码为 UTF-8 字节,以 256 种字节为基础单元执行合并。合并规则依然是频率统计,没有随机采样,也不要求词表包含完整单词。

Q4. 关于 BPE 的解码过程,以下说法正确的是?

单选题 · mid

  • A.需要先训练一个语言模型
  • B.将子词按字节数大小排序后拼接
  • C.直接拼接所有子词即可还原原文← 正确答案
  • D.解码必须依赖词性标注的信息

答案:C。BPE 编码是可逆的:每个子词都是原文本的连续片段,解码时按顺序直接拼接就能无损还原原文,就像把乐高组件按拼装顺序拆下来再原样装回去。不需要语言模型、排序或词性标注参与。

Q5. BPE 与 WordPiece 最核心的差异在于?

单选题 · mid

  • A.合并依据从频率换成了概率比得分← 正确答案
  • B.BPE 无法处理英文之外的语料
  • C.WordPiece 不需要初始字符表
  • D.BPE 只合并单独的单个字符

答案:A。BPE 以相邻对的原始频率为合并依据,而 WordPiece 用 freq(xy) 除以 freq(x)·freq(y) 的概率比得分,优先合并“共现超出偶然”的组合。两者都支持多语言、都需要初始词表,BPE 也不限于单字符合并。

Q6. BPE 子词切分带来的好处包括哪些?

多选题 · mid

  • A.控制词表大小避免无限膨胀← 正确答案
  • B.缓解未登录词导致的 OOV 问题← 正确答案
  • C.缩短序列长度提升计算效率← 正确答案
  • D.让模型直接理解单词语义

答案:ABC。BPE 用有限数量的子词组合表示无限多的单词,词表可控;生词可拆成已知子词,OOV 大幅缓解;高频词合并成单 token,序列变短、计算加速。但 BPE 只是切分工具,不负责让模型“理解”语义,D 错在把分词等同于语义理解。

Q7. 当语料中出现词表外的单词时,BPE 通常会怎么做?

单选题 · mid

  • A.丢弃该单词不参与后续训练
  • B.拆解为已知的字节或字符← 正确答案
  • C.随机替换成相近的英文单词
  • D.报错并终止程序的运行

答案:B。BPE 的兜底策略是“向下拆解”:词表中没有整个单词,就找最长的子词;子词也没有,就拆到单个字符,甚至拆到 UTF-8 字节。这种设计让任何生词都能被编码,而不是丢弃、替换或报错。

Q8. 关于 BPE 词汇表的构建过程,以下说法正确的有哪些?

多选题 · hard

  • A.初始词表包含语料的全部独立字符← 正确答案
  • B.每次合并让词表容量恰好增加一个← 正确答案
  • C.总的合并次数由人工预先设定← 正确答案
  • D.最终词表大小与语料规模成反比

答案:ABC。BPE 从字符集出发,每合并一次就新增一个子词条目,因此 |V| = 初始字符数 + 合并次数,A、B 正确;合并次数通常由人根据目标词表大小设定,C 正确。词表大小与语料规模没有“成反比”的固定关系,D 错误。

Q9. SentencePiece 相比经典 BPE 的独特设计是什么?

单选题 · hard

  • A.将空格也视作普通字符参与合并← 正确答案
  • B.完全不使用频率统计的方法
  • C.只能用于中文文本的切分
  • D.词表在推理阶段动态扩展

答案:A。经典 BPE 默认按空格分词后处理词内部,空格被排除在统计之外;SentencePiece 把空格当作一个普通字符()参与合并,这样分词结果可无损还原,适用于日语等无空格语言。它依然用频率统计,不只支持中文,词表在训练后冻结。

Q10. 关于词表大小与序列长度的权衡,以下说法正确的有哪些?

多选题 · hard

  • A.词表越大单个 Token 信息越丰富← 正确答案
  • B.词表过大会导致嵌入层参数暴涨← 正确答案
  • C.词表偏小会让序列变得冗长← 正确答案
  • D.词表大小与训练速度没有关系

答案:ABC。词表越大,高频词越可能成为独立 token,单 token 承载信息越多、序列越短;但嵌入矩阵的行数等于词表大小,词表翻倍参数也翻倍,B 正确;词表偏小则长词被拆碎,序列变长,Transformer 的计算量随序列长度平方增长,训练速度因此受影响,D 错误。