06 Tokenizer 详解:BPE、WordPiece、SentencePiece 有什么区别?

在前面几章中,我们已经介绍了 Transformer、Self-Attention 和 GPT 为什么使用 Decoder-only 架构。到这里,一个非常基础但容易被忽略的问题出现了:

文本到底是如何进入大语言模型的?

我们平时看到的是一句自然语言:

复制代码
大语言模型正在改变人工智能的发展方式。

但是模型不能直接处理中文、英文或代码字符串。对模型来说,输入必须先被转换成数字 ID,再经过 embedding 层变成向量,最后才能进入 Transformer。这个过程就是 Tokenization ,负责执行这个过程的工具就是 Tokenizer

简单来说:

复制代码
原始文本
  ↓
Tokenizer
  ↓
token 序列
  ↓
token ID 序列
  ↓
Embedding
  ↓
Transformer

所以,Tokenizer 是大语言模型的第一道入口。它决定了文本如何被切分,也直接影响模型的词表大小、序列长度、训练效率、多语言能力、代码能力和长上下文成本。

本文重点讲三个常见概念:

复制代码
BPE
WordPiece
SentencePiece

它们都是大语言模型和预训练语言模型中非常重要的分词方法。


一、为什么大语言模型需要 Tokenizer?

语言模型的训练目标通常是预测下一个 token。

例如 GPT 类模型要学习:

复制代码
给定前面的 token,预测下一个 token

假设一句话是:

复制代码
我喜欢机器学习

如果按字切分,可以得到:

复制代码
我 / 喜 / 欢 / 机 / 器 / 学 / 习

如果按词切分,可以得到:

复制代码
我 / 喜欢 / 机器学习

如果按子词切分,可能得到:

复制代码
我 / 喜欢 / 机器 / 学习

这些切分方式都会影响模型看到的输入序列。

Tokenizer 的核心作用有三个。

第一,把文本切成适合模型处理的基本单位。

第二,把每个 token 映射成一个整数 ID。

第三,控制词表规模和序列长度之间的平衡。

例如:

复制代码
文本:大语言模型
token:大 / 语言 / 模型
token ID:[1024, 2356, 987]

模型真正看到的不是"语言"这个汉字字符串,而是它对应的 ID。之后 embedding 层会把这个 ID 映射成向量。

所以,在大语言模型中:

Tokenizer 决定文本如何被模型"看见"。


二、为什么不能简单按词或按字切分?

最直观的分词方式有两种:按词切分和按字符切分。但这两种方式都有明显问题。

1. 按词切分的问题

如果按词切分,英文句子:

复制代码
I like machine learning.

可以切成:

复制代码
I / like / machine / learning

看起来很自然。

但是按词切分会遇到词表爆炸问题。因为自然语言中的词非常多,尤其是英文中存在大量词形变化:

复制代码
learn
learns
learned
learning
learner

如果每个词都放进词表,词表会非常大。更麻烦的是,模型很容易遇到训练集中没见过的新词。例如:

复制代码
DeepSeek-V3
Qwen2.5-VL
ChatGPT-like
bioinformatics

如果词表中没有这些词,就会出现 OOV,也就是 out-of-vocabulary 问题。

2. 按字符切分的问题

另一种极端方式是按字符切分。例如:

复制代码
learning

切成:

复制代码
l / e / a / r / n / i / n / g

这样几乎不会有 OOV,因为任何词都可以由字符组成。但是问题是序列会变得很长。

例如:

复制代码
internationalization

如果按词看是 1 个 token,如果按字符切分就会变成很多 token。序列越长,Transformer 的计算成本越高。标准 Self-Attention 的复杂度大致是:

复制代码
O(n²)

其中 n 是 token 数量。所以,按字符切分虽然避免了 OOV,但会显著增加序列长度和计算成本。

3. 子词切分是折中方案

因此,现代大语言模型通常采用子词切分,也就是 subword tokenization。它介于"词"和"字符"之间。常见词可以作为完整 token:

复制代码
learning

罕见词可以拆成多个子词:

复制代码
bio / informatics

或者:

复制代码
un / believable

子词切分的核心思想是:

常见片段尽量合并,罕见词可以拆开表示。

这样既避免了词表过大,又减少了字符级切分导致的序列过长问题。


三、BPE:从字符开始,不断合并高频片段

BPE,全称是 Byte Pair Encoding

它最初是一种数据压缩思想,后来被引入到神经机器翻译中,用来解决罕见词和开放词表问题。BPE 的核心思想很简单:

从最小单位开始,反复合并出现频率最高的相邻片段,直到达到设定的词表大小。

为了理解 BPE,我们看一个简化例子。假设语料中有几个词:

复制代码
low
lower
lowest

一开始可以拆成字符:

复制代码
l o w
l o w e r
l o w e s t

统计相邻字符对的频率,发现:

复制代码
l + o
o + w

经常一起出现。于是 BPE 可能先把:

复制代码
l + o → lo

再把:

复制代码
lo + w → low

这样,"low" 就变成了一个子词 token。继续合并后,可能得到:

复制代码
low
er
est

于是:

复制代码
lower → low / er
lowest → low / est

这样,模型既能保留常见词根,又能处理不同词形变化。BPE 的训练过程可以概括为:

复制代码
1. 把文本拆成初始符号,通常是字符或字节
2. 统计所有相邻符号对的出现频率
3. 合并频率最高的符号对
4. 更新语料表示
5. 重复合并,直到达到目标词表大小

BPE 的优点是:

复制代码
简单直观
容易实现
能有效缓解 OOV
适合开放词表建模

它的局限是:

复制代码
主要基于频率合并,不一定符合语言学意义
对空格、标点、多语言文本的处理需要额外设计
不同训练语料会得到不同词表

在大语言模型中,BPE 及其变体非常常见。GPT 系列中就广泛使用了 BPE 或 byte-level BPE 思路。


四、WordPiece:BERT 常用的子词切分方法

WordPiece 和 BPE 很像,也是一种子词分词方法。BERT 使用的就是 WordPiece 词表。WordPiece 的基本目标也是把词拆成更小的子词单元。例如:

复制代码
unbelievable

可能被切成:

复制代码
un / ##believable

或者:

复制代码
un / ##believ / ##able

这里的 ## 表示这个子词不是一个新词的开头,而是接在前一个子词后面。例如:

复制代码
playing → play / ##ing

其中:

复制代码
play

是词的开头,而:

复制代码
##ing

表示它是后缀片段。WordPiece 在推理时通常采用 longest-match-first,也就是最长匹配优先策略。例如模型要切分:

复制代码
unaffable

它会从词表中寻找最长的可匹配子词。如果整个词不在词表中,就尝试匹配较长前缀,再继续处理剩余部分。可以简单理解为:

复制代码
从左到右
每一步尽量匹配词表中最长的子词
匹配不到就继续拆得更细

WordPiece 的特点是:

复制代码
适合 BERT 这类预训练语言模型
使用 ## 标记词内子词
推理时常用最长匹配
能够处理未登录词

它和 BPE 的区别可以粗略理解为:

复制代码
BPE 更强调频繁相邻片段的逐步合并
WordPiece 更强调基于词表的子词匹配与概率建模思想

不过从使用者角度看,二者都属于 subword tokenization,都在解决"词表大小"和"未登录词"之间的平衡问题。


五、SentencePiece:不是一种单独算法,而是一套更通用的分词框架

SentencePiece 很容易被误解。很多人会把它和 BPE、WordPiece 并列,认为它们是三种同级别算法。但更准确地说:

SentencePiece 是一个语言无关的 tokenizer 工具框架,它可以实现 BPE,也可以实现 Unigram Language Model。

它最大的特点是:

复制代码
可以直接从原始文本训练 tokenizer
不要求文本预先按空格切词
适合中文、日文等没有天然空格分隔的语言

传统英文分词方法往往默认文本中有空格。例如:

复制代码
I love machine learning.

空格天然分隔单词。但是中文没有这种空格:

复制代码
我喜欢机器学习

如果 tokenizer 强依赖空格,处理中文、日文等语言时就会比较麻烦。SentencePiece 的做法是把文本当作普通字符序列处理,并把空格也视为一种普通符号。它常用特殊符号:

复制代码

来表示空格。例如英文句子:

复制代码
I love NLP

可能被表示为:

复制代码
▁I / ▁love / ▁NLP

这里的 表示词前空格。这样做的好处是:

复制代码
分词和反分词更统一
不依赖外部预分词器
对多语言更友好
可以直接从 raw text 训练

SentencePiece 支持两种常见模型:

复制代码
BPE
Unigram Language Model

其中 Unigram 方法不是从小片段不断合并,而是先准备一个较大的候选子词集合,然后通过概率模型逐步筛选出更优词表。

所以,SentencePiece 更像是一个统一工具:

复制代码
你可以用 SentencePiece 训练 BPE tokenizer
也可以用 SentencePiece 训练 Unigram tokenizer

很多大模型和多语言模型都会使用 SentencePiece 或其变体,因为它对多语言和无空格语言更加友好。


六、BPE、WordPiece、SentencePiece 对比

现在我们把三者放在一起比较。

方法 常见代表 核心思想 主要特点
BPE GPT 系列、很多生成模型 从小单位开始,不断合并高频相邻片段 简单、高效、适合开放词表
WordPiece BERT 基于子词词表进行最长匹配 常用 ## 表示词内片段
SentencePiece T5、LLaMA 等模型常见 从原始文本直接训练 tokenizer,可实现 BPE 或 Unigram 语言无关,适合多语言和无空格语言

可以这样理解:

复制代码
BPE 更像是一种子词合并算法
WordPiece 更像是 BERT 系列常用的子词词表方法
SentencePiece 更像是一套 tokenizer 工具框架

三者都不是简单的"按词分词",而是通过子词单位在词表规模和表达能力之间做平衡。

如果用一句话总结:

BPE 关注高频片段合并,WordPiece 关注词表内最长子词匹配,SentencePiece 关注从原始文本端到端训练语言无关 tokenizer。


七、Tokenizer 对大语言模型有什么影响?

Tokenizer 看起来只是预处理工具,但它对模型影响很大。

1. 影响序列长度

同一句话,不同 tokenizer 切出来的 token 数量可能不同。

例如:

复制代码
DeepSeek-V3 is powerful.

一个 tokenizer 可能切成:

复制代码
DeepSeek / - / V / 3 / is / powerful

另一个 tokenizer 可能切成:

复制代码
Deep / Seek / - / V / 3 / is / power / ful

token 数量越多,模型处理成本越高。对于 Transformer 来说,token 数量还会影响注意力计算成本。

2. 影响多语言能力

如果词表主要由英文语料训练得到,那么中文、日文、阿拉伯文等语言可能会被切得很碎。

例如中文:

复制代码
人工智能

如果 tokenizer 不适合中文,可能会切成非常细的单位,导致同样一句中文占用更多 token。这会影响模型的训练效率和推理成本。

3. 影响代码能力

代码中有大量特殊符号:

复制代码
def get_user_info(user_id):
    return user_dict[user_id]

如果 tokenizer 不能很好处理下划线、缩进、括号、运算符、变量名,代码会被切得很碎。因此,代码大模型通常需要特别关注 tokenizer 对代码语料的适配能力。

4. 影响长上下文成本

大模型的上下文长度通常按 token 计算,而不是按字符或汉字计算。例如模型支持:

复制代码
128K tokens

这不等于支持 128K 个汉字或 128K 个英文单词。如果 tokenizer 对某种语言切得很碎,那么同样长度的文本会占用更多 token,从而更快达到上下文上限。

5. 影响未知词和新词处理

大语言模型会不断遇到新词,例如:

复制代码
新模型名称
论文缩写
变量名
网络热词
专有名词

好的 tokenizer 应该能把这些词拆成合理片段,而不是全部变成未知符号。现代子词 tokenizer 的一个重要优势就是减少 [UNK] 的出现。


八、本文小结

本文介绍了大语言模型中的 Tokenizer,并重点比较了 BPE、WordPiece 和 SentencePiece。Tokenizer 的作用是:

复制代码
把原始文本转换成 token ID 序列

完整流程是:

复制代码
文本
  ↓
Tokenizer
  ↓
token
  ↓
token ID
  ↓
Embedding
  ↓
Transformer

按词切分会导致词表过大和未登录词问题,按字符切分又会导致序列过长。因此,现代大语言模型通常采用子词切分。BPE 的核心思想是:

复制代码
从字符或字节开始,不断合并高频相邻片段。

WordPiece 是 BERT 常用的子词方法,推理时通常采用最长匹配优先,并使用 ## 表示词内子词。SentencePiece 更像是一套语言无关的 tokenizer 框架,它可以直接从原始文本训练 tokenizer,并支持 BPE 和 Unigram 等方法,因此更适合多语言场景。

三者的关系可以简单概括为:

复制代码
BPE:一种高频合并式子词算法
WordPiece:BERT 系列常用的子词词表方法
SentencePiece:语言无关的 tokenizer 工具框架

Tokenizer 虽然不是 Transformer 的主体结构,但它直接影响模型的输入形式、序列长度、多语言能力、代码能力和推理成本。如果说 Transformer 决定了模型如何处理 token,那么 Tokenizer 决定了:

什么样的文本会被切成什么样的 token。

相关推荐
bloxed14 小时前
【AI大模型--NumPy-07】高级线性代数完全指南
人工智能·线性代数·numpy
SLD_Allen14 小时前
从Prompt、Context到Harness,工程的三次进化与终局之战
人工智能·prompt
HKT_China14 小时前
5G IoT升级营运模式,打通数据脉络,驱动AI应用
人工智能·物联网·5g·iot
weixin_4684668514 小时前
PyTorch 深度学习框架核心能力与实战评测
人工智能·pytorch·深度学习·神经网络·计算机视觉·动态图·模型训练
薛会14 小时前
当世界模型学会”想”和”造”:3D-Belief 与 GigaWorld-0 揭示的两条进化路线
人工智能·深度学习·机器学习
G***技14 小时前
IB3-771:为智慧工厂巡检机器人打造“感知-决策-执行”一体化控制核心
人工智能·嵌入式主板
海兰14 小时前
手把手elasticsearch学习之构建 HITL AI 代理
人工智能·学习·elasticsearch
zhangxingchao14 小时前
AI 大模型核心五:从 Transformer、RAG 到 Agent 架构
前端·人工智能·后端
weixin_3975740914 小时前
食品包装AI质检系统技术实现:从OCR提取到合规检测全链路
人工智能·ocr