💡

文章摘要

分词器(Tokenizer)是LLM处理文本的第一道工序,决定了模型如何「看见」语言。本文从最基础的字符级分词出发,系统讲解BPE、WordPiece、Unigram、SentencePiece四大算法的原理与差异,对比tiktoken与HuggingFace Tokenizers两大工程实现,并给出2026年主流LLM的分词器选型全景图。

一、为什么分词器是LLM的基石

分词器定义了模型如何「看见」语言

大语言模型不直接处理文字——它处理的是整数序列。分词器(Tokenizer)就是完成「文字→整数」转换的第一道工序。这个看似简单的步骤,实际上决定了模型对语言的几乎所有基本认知:

  1. 词汇边界:「hugging」是一个词还是「hug」+「ging」两个子词?不同的分词方式直接影响模型对词义的理解
  2. 上下文窗口利用率:同样的文本,用不同分词器可能产生差异2-3倍的token数量。这意味着同样的128K上下文窗口,能容纳的实际内容量完全不同
  3. 多语言能力:分词器对中文、日文、阿拉伯文等非拉丁文字的处理效率差异巨大。一个为英文优化的分词器,处理中文时可能需要3-5倍的token数量
  4. 推理成本:API按token计费。分词效率低意味着同样的内容要付更多钱

分词器的三个层次

分词技术经历了三个发展阶段:

词级(Word-level):最直觉的方式——按空格和标点切分。问题是词汇表爆炸:英语有超过100万个词,加上变形和专有名词,词表可能达到百万级。每个词对应一个embedding向量,百万级词表的embedding层就需要数GB内存。

字符级(Character-level):走向另一个极端——每个字符一个token。词表极小(几十个字符),但序列长度爆炸:「hello」变成5个token,「unbelievable」变成12个。更严重的是,字符级分词丢失了词义信息,模型需要更深的网络才能学到等价表示。

子词级(Subword-level):2026年LLM的标准选择。在词级和字符级之间找到平衡——常见词保持完整,罕见词拆分为子词。例如「unbelievable」可能拆分为「un」+「believ」+「able」三个子词token,既控制了词表大小,又保留了有意义的语义单元。

分词器的经济学影响

一个具体的例子:同样一句「今天天气很好」,在不同分词器下的token数量差异:

  • GPT-4的o200k分词器:约4-5个token(中文优化后)
  • GPT-4的cl100k分词器:约7-8个token
  • Llama 2的SentencePiece:约10-12个token
  • 纯字符级:5个token(每个汉字一个token

看似差异不大,但当处理百万级文档时,这些差异会累积成显著的成本和延迟差距。

图表加载中…

💡 一句话理解

分词器不是简单的「预处理」——它是模型架构的一部分。更换分词器意味着模型的embedding层和输出层都需要重新训练,因为词表变了。

⚠️ 常见踩坑

不同模型的tokenizer不兼容。GPT-4的tokenizer输出的token ID与Llama的完全不同,即使输入同一段文本。跨模型比较token数量没有意义。

二、BPE算法:从数据压缩到NLP基石

BPE的历史:从压缩算法到NLP

字节对编码Byte Pair Encoding, BPE)最初是一种数据压缩算法,由Philip Gage在1994年提出。其核心思想极其简单:

  1. 从字符级开始,统计所有相邻字符对的出现频率
  2. 找到出现频率最高的字符对,将其合并为一个新符号
  3. 重复步骤1-2,直到达到目标词表大小

例如,在一个英文语料中:

  • 初始:h, e, l, l, o(每个字符独立)
  • 第1轮合并:「t」+「h」→「th」(因为「th」出现最频繁)
  • 第2轮合并:「th」+「e」→「the」
  • 第N轮合并:逐步构建出常见的子词单元

BPE在NLP中的应用

2015年,Sennrich等人将BPE引入神经机器翻译,发表了里程碑论文「Neural Machine Translation of Rare Words with Subword Units」。他们发现BPE能优雅地处理未登录词(OOV):

  • 训练时见过的词:作为整体token
  • 训练时没见过的词:拆分为已知的子词组合
  • 极端情况:退化为字符级,但不会完全无法处理

BPE的训练过程详解

BPE训练的核心是一个贪心合并过程:

  1. 初始化:将训练语料切分为字符序列。每个字符是一个基础token
  2. 统计频率:遍历整个语料,统计所有相邻token对的出现次数
  3. 选择最优合并:找到频率最高的token对,创建新token
  4. 应用合并:在语料中将该token对替换为新token
  5. 重复:回到步骤2,直到词表达到预设大小(通常30K-200K)

时间复杂度:每轮需要遍历整个语料统计频率,合并次数为词表大小减去初始字符集大小。总体复杂度约为$O(N \times V)$,其中$N$是语料总长度,$V$是目标词表大小。

BPE的变体

原始BPE有多个工程变体:

  • Byte-level BPE:在UTF-8字节层面操作,而非Unicode字符层面。GPT系列和tiktoken使用这种方式,好处是词表可以覆盖所有可能的字节序列,永远不会出现UNK(未知字符)
  • Regex BPE:在BPE合并规则之上叠加正则表达式预分词。GPT-4的cl100k分词器使用约100条正则规则来处理特殊token(如<|endoftext|>)和格式化
  • 后缀感知BPE:在合并时考虑词缀信息,避免跨词根边界的合并
图表加载中…

💡 一句话理解

BPE的核心优势是简单高效。它不需要训练神经网络,只需要统计频率和合并操作。一个30K词表的BPE训练通常只需几分钟。

⚠️ 常见踩坑

BPE的合并顺序是确定的但不可逆——一旦两个token被合并,后续无法拆分。这意味着训练语料的质量直接决定了分词器的质量。

三、WordPiece与Unigram:两种不同的子词学习策略

WordPiece:基于似然的贪心合并

WordPiece由Google在2016年的论文中提出,用于BERT等模型的预训练。它与BPE的核心区别在于合并标准

  • BPE:选择出现频率最高token对进行合并
  • WordPiece:选择使训练数据似然增益最大token对进行合并

具体来说,WordPiece计算每对token合并后对整体语言模型似然的贡献:

$$\text{score}(a, b) = \frac{\text{count}(ab)}{\text{count}(a) \times \text{count}(b)}$$

这个公式的含义是:如果「ab」作为一个整体的出现频率远高于「a」和「b」独立出现频率的乘积,说明它们有很强的结合倾向,应该合并。

WordPiece的编码方式

WordPiece使用贪心最长匹配(Greedy Longest Match)进行编码:

  1. 从文本开头开始
  2. 尝试匹配词表中最长的token
  3. 如果匹配成功,输出该token,从未匹配位置继续
  4. 如果匹配失败,回退到单个字符

例如,对于「unhappiness」:

  • 尝试匹配「unhappiness」→ 不在词表中
  • 尝试匹配「unhappines」→ 不在词表中
  • ...
  • 匹配「un」→ 在词表中,输出
  • 从「happiness」继续,匹配「happi」→ 在词表中
  • 继续「ness」→ 在词表中
  • 最终:「un」+「happi」+「ness」

Unigram语言模型:从大到小的剪枝策略

Unigram模型由Taku Kudo在2018年提出,采用了与BPE/WordPiece完全相反的策略:

  • BPE/WordPiece:从最小开始,逐步合并(自底向上)
  • Unigram:从最大开始,逐步剪枝(自顶向下)

Unigram的训练过程:

  1. 初始化大词表:从训练语料中提取所有高频字符n-gram,构建一个初始词表(通常为目标大小的10-100倍)
  2. 计算最优分词:使用Viterbi算法,在当前词表上找到使训练数据似然最大的分词方案
  3. 计算剪枝损失:对每个token,计算如果从词表中移除它,训练数据似然会下降多少
  4. 剪枝:移除损失最小的token(通常是低频或冗余的token
  5. 重复:回到步骤2,直到词表缩小到目标大小

Unigram的关键优势:

  • 概率模型:每个token有明确的概率,可以计算分词的不确定性
  • 多种合理分词:可以输出多个高概率的分词方案(类似采样)
  • 子词正则化:训练时随机选择次优分词,增加模型鲁棒性

三种算法的对比

特性 BPE WordPiece Unigram
合并策略 频率最高 似然增益最大 剪枝损失最小
方向 自底向上 自底向上 自顶向下
概率模型 隐式 显式
子词正则化 不支持 不支持 原生支持
典型使用 GPT, LLaMA 3 BERT, DistilBERT T5, Gemma

💡 一句话理解

如果你只需要一个确定性分词器,BPE足够好。如果你需要训练时的数据增强(子词正则化),Unigram是唯一原生支持的方案。

⚠️ 常见踩坑

WordPiece的贪心最长匹配可能导致非直觉的分词结果。例如「hugging」可能被分为「hug」+「ging」而不是「hugg」+「ing」,因为贪心匹配优先选择最长前缀。

四、SentencePiece:语言无关的分词框架

为什么需要SentencePiece?

BPE和WordPiece都有一个共同的工程问题:需要预分词(Pre-tokenization

传统BPE在训练前需要先将文本按空格和标点切分为单词,然后在单词内部运行BPE合并。这带来两个问题:

  1. 空格依赖:中文、日文、泰文等语言没有空格分隔单词,预分词规则需要单独设计
  2. 预处理不一致:不同语言的预分词规则不同,导致同一套pipeline难以处理多语言

SentencePiece由Google的Taku Kudo和John Richardson在2018年提出,核心创新是:直接在原始Unicode文本上操作,不需要任何预分词

SentencePiece的工作方式

SentencePiece将空白字符显式表示为特殊符号「▁」(U+2581,Lower One Eighth Block):

  • 「Hello world」→「▁Hello」+「▁world」
  • 「你好世界」→「▁你」+「▁好」+「▁世」+「▁界」

这样做的好处是:空白字符被当作普通字符处理,模型可以学习到「词首」「词中」的位置信息。

SentencePiece的两种训练模式

SentencePiece本身是一个框架,支持两种底层算法:

  1. BPE模式:使用字节对编码进行合并,与标准BPE类似但在原始文本上操作
  2. Unigram模式:使用Unigram语言模型进行剪枝

选择哪种模式取决于需求:

  • 需要确定性分词 → BPE模式
  • 需要子词正则化 → Unigram模式

SentencePiece vs tiktoken:两大工程实现

2026年的LLM生态中,两大分词器实现占据了主导地位:

SentencePiece(Llama 2, Gemma, T5等使用):

  • 直接在Unicode code point层面操作
  • 支持BPE和Unigram两种算法
  • 对罕见字符有byte fallback机制
  • 词表通常32K-256K
  • 多语言覆盖好,但拉丁文字效率略低

tiktoken(GPT系列, Llama 3+使用):

  • 在UTF-8字节层面操作
  • BPE算法,叠加正则预分词规则
  • 永远不会出现UNK(字节级覆盖)
  • 词表50K-200K
  • Rust实现,速度极快
  • 不支持训练自定义分词器

关键差异:中文处理

以中文「机器学习很有趣」为例:

  • tiktoken(字节级BPE:先将中文转为UTF-8字节(每个汉字3字节),然后在字节层面做BPE合并。常用汉字会被合并为单token,但罕见汉字可能拆为2-3个字节token
  • SentencePiece(code point级BPE:直接在汉字层面操作。常用汉字为单token,罕见汉字通过byte fallback拆为字节

实际效果:对于中文文本,SentencePiece的token效率通常比tiktoken略高(约10-20%),因为code point级别的操作避免了UTF-8编码的中间步骤。但tiktoken在GPT-4o的o200k词表中做了大量中文优化,差距已经很小。

2026年主流LLM的分词器选型

模型系列 分词器 词表大小 算法
GPT-4o/GPT-5 tiktoken o200k ~200K Byte-level BPE
GPT-3.5/GPT-4 tiktoken cl100k ~100K Byte-level BPE
LLaMA 2 SentencePiece 32K BPE模式
LLaMA 3/3.1/4 tiktoken风格 128K Byte-level BPE
Gemma/Gemma 2 SentencePiece 256K Unigram模式
Claude 3/3.5 专有BPE 未公开 BPE风格
Qwen 2/2.5 tiktoken风格 152K Byte-level BPE
Mistral SentencePiece 32K BPE模式
T5/mT5 SentencePiece 32K/250K Unigram模式

💡 一句话理解

如果你要训练新的LLM且需要多语言支持,SentencePiece的Unigram模式是最安全的选择。如果你只做英文且追求速度,tiktoken是最快的。

⚠️ 常见踩坑

tiktoken不支持训练自定义分词器。如果你需要为新语言或领域定制分词器,必须使用SentencePiece或HuggingFace Tokenizers。

五、分词器的性能指标与评估方法

Fertility(繁殖率)

分词器性能最核心的指标是Fertility——即token数与词数的比值。Fertility越低,分词效率越高:

$$\text{Fertility} = \frac{\text{Token数量}}{\text{Word数量}}$$

理想情况下,每个词对应1个token(Fertility=1)。实际中:

  • 英文:好的分词器Fertility约1.2-1.4
  • 中文:好的分词器Fertility约1.0-1.5(每字1-1.5 token
  • 低资源语言:Fertility可能达到2.0-5.0

Bits per Character(BPC)

BPC衡量分词器的信息编码效率:

$$\text{BPC} = \frac{-\log_2 P(\text{text})}{\text{字符数}}$$

BPC越低,说明分词器对文本的压缩效率越高。理想的分词器接近英语的熵值(约1.0 bit/character)。

词表覆盖率

给定词表大小,能覆盖训练语料中多少比例的token出现次数:

  • 30K词表:覆盖约97-98%的英文语料
  • 50K词表:覆盖约98-99%
  • 100K词表:覆盖约99-99.5%
  • 200K词表:覆盖约99.5%+

边际收益递减:从30K到100K提升约2%,从100K到200K只提升约0.5%。但每个新token都需要对应的embedding向量,词表越大,embedding层的内存和计算开销越高。

多语言Fertility对比

以同一段联合国人权宣言的多语言版本为例:

语言 原文字符数 tiktoken cl100k tokens SentencePiece 32K tokens Gemma SP 256K tokens
英文 ~4500 ~5800 ~6200 ~5500
中文 ~1500 ~2200 ~1800 ~1600
日文 ~2000 ~3500 ~2800 ~2400
阿拉伯文 ~3000 ~5000 ~4500 ~3800
印地文 ~3500 ~6000 ~5500 ~4200

数据说明:cl100k对中文的处理效率不如SentencePiece(因为cl100k的词表以英文为主),但GPT-4o的o200k已经大幅改善了这一问题。Gemma的256K大词表在所有语言上都表现优异,但代价是更大的embedding层。

分词器对模型性能的影响

分词器不仅影响效率,还影响模型质量:

  1. 语义完整性:如果一个常用词被拆分为太多子词,模型需要更多层才能学到它的完整语义
  2. 跨语言迁移:多语言分词器如果某种语言的Fertility过高,该语言的性能通常较差
  3. 代码理解:代码中的特殊符号(如「->」「!=」「{」)如果被拆分为多个token,模型对代码结构的理解能力下降

2025年的一项研究(SuperBPE)表明,在保持词表大小不变的情况下,优化分词器的Fertility可以带来1-3%的下游任务提升,且对低资源语言的提升更为显著。

💡 一句话理解

评估分词器质量的第一指标是Fertility。在你的目标语言和目标领域上测量Fertility,比看任何benchmark都直接。

⚠️ 常见踩坑

不要跨分词器比较token数量。GPT-4的1000个token和Llama 3的1000个token代表的文本量可能差2倍。

六、工程实践:HuggingFace Tokenizers与BlockBPE

HuggingFace Tokenizers

HuggingFace的Tokenizers库是2026年使用最广泛的分词器实现,几乎与Transformers库深度绑定。其核心特点:

  1. Rust实现:核心分词逻辑用Rust编写,单线程速度比旧版Python实现快10-100倍
  2. 多算法支持BPE、WordPiece、Unigram均有实现
  3. 预训练分词器托管:HuggingFace Hub上托管了超过50万个预训练分词器,可直接加载
  4. 自定义训练:支持在自定义语料上训练新的分词器

训练自定义分词器的典型流程

使用HuggingFace Tokenizers训练一个BPE分词器的关键步骤:

  1. 准备训练语料:通常1-10GB的目标领域文本
  2. 配置分词器:选择算法(BPE/WordPiece/Unigram)、词表大小、特殊token
  3. 训练:调用tokenizer.train()方法,通常几分钟到几十分钟
  4. 评估:在测试集上计算Fertility和覆盖率
  5. 部署:保存为JSON文件,加载到推理pipeline

BlockBPE:并行化的新前沿

2025年发表的BlockBPE代表了分词器性能的新突破。它的核心创新是将BPE的串行合并过程并行化

传统BPE的合并是严格串行的——每次合并后需要重新统计频率。BlockBPE发现,在一次合并中,多个不重叠的token对可以同时合并而不冲突。利用这一特性,BlockBPE在GPU上实现了:

  • 比tiktoken快2倍的吞吐量
  • 比HuggingFace Tokenizers快2.5倍的吞吐量
  • 在高batch推理场景下优势更明显

分词器的部署注意事项

在生产环境中,分词器的工程考量包括:

  1. 延迟:分词本身需要时间。对于短文本(<100字符),分词延迟可能占总prefill延迟的10-20%
  2. 一致性:训练和推理必须使用完全相同的分词器版本。版本不一致会导致token ID偏移,模型输出完全错误
  3. 特殊token:不同模型使用不同的特殊token(如<|endoftext|>、[CLS]、[SEP]),必须严格匹配
  4. 内存:分词器本身占用内存不大(通常<100MB),但词表到embedding的映射需要GPU内存

分词器版本管理

一个容易被忽视的工程问题:分词器版本必须与模型版本严格对应。

  • LLaMA 3.0和LLaMA 3.1的分词器词表相同但合并规则可能不同
  • GPT-4从cl100k升级到o200k时,同样的文本产生的token ID完全不同
  • 如果你fine-tune了模型但使用了基础模型的分词器,可能导致性能下降

最佳实践:将分词器文件与模型权重一起版本管理,不要依赖「最新版本的默认分词器」。

💡 一句话理解

生产环境中最常见的分词器bug是版本不一致。建议在模型部署脚本中显式指定分词器文件路径,不要依赖自动解析。

⚠️ 常见踩坑

HuggingFace的AutoTokenizer方便但有风险——它可能在你不知情的情况下更新分词器版本。生产环境建议锁定具体版本。

七、前沿趋势:分词器的未来方向

趋势1:更大词表成为主流

2023年,主流LLM的词表大小为32K-50K。到2026年,趋势已经转向100K-256K:

  • GPT-4o: 200K(o200k)
  • LLaMA 3/4: 128K
  • Gemma 2: 256K
  • Qwen 2.5: 152K

大词表的好处是直接且明显的:Fertility降低、上下文利用率提高、多语言性能提升。代价是embedding层更大(256K×4096维的embedding需要约2GB内存),但这在2026年的GPU容量下已不是问题。

趋势2:领域自适应分词器

通用分词器在特定领域(如医学、法律、代码)的Fertility通常较高。2025-2026年的趋势是针对特定领域训练专用分词器:

  • 代码分词器:将常见的代码模式(如「def init(self)」)作为单token
  • 医学分词器:将医学术语(如「myocardial infarction」)保持完整
  • 法律分词器:将法律术语和条款编号作为单token

IndicSuperTokenizer(2025)的研究表明,领域自适应分词器可以在不增加词表大小的情况下,将特定领域的Fertility降低15-30%。

趋势3:分词器与模型联合训练

传统做法是先固定分词器,再训练模型。但分词器的选择实际上影响模型的表示学习。2025年开始出现分词器与模型联合优化的研究:

  • Soft Tokenization:将分词过程软化为可微操作,允许梯度回传到分词决策
  • Adaptive Vocabulary:训练过程中动态调整词表——合并低频token、拆分高频token
  • Tokenizer-aware Loss:在损失函数中考虑分词的不确定性

趋势4:超越BPE的新算法

BPE统治了十年,但研究者正在探索替代方案:

  • SuperBPE(2025):在BPE基础上引入语义信息指导合并,不仅看频率还看语义一致性
  • Scaffold-BPE(2024):迭代剪枝低频token,减少词表中的不平衡
  • PickyBPE(2024):丢弃「无信息量」的合并,提高词表利用率
  • RWKV World Tokenizer:使用完全不同的算法,在Rust中实现,速度比tiktoken快10倍(单线程)

趋势5:多模态分词器

随着多模态模型的普及,分词器不再只处理文本:

  • 视觉token:将图像切分为patch token(如ViT的16×16 patch)
  • 音频token:将音频波形编码为离散token(如AudioLM、Whisper
  • 统一分词器:将文本、图像、音频映射到同一个token空间

这对分词器的设计提出了全新挑战:不同模态的token需要在语义空间中对齐,同时保持各自的编码效率。

💡 一句话理解

如果你在2026年启动新的LLM项目,建议使用≥128K词表。大词表的成本(额外embedding内存)很低,但收益(Fertility降低、多语言改善)很显著。

⚠️ 常见踩坑

分词器联合训练仍处于研究阶段,不建议在生产中使用。当前最稳妥的做法仍然是:先用标准算法训练分词器,再用固定分词器训练模型。

🎯 相关面试题

巩固本篇知识点,备战 AI 岗位面试。