1994年2月,Philip Gage在《C Users Journal》上发表了一篇题为"A New Algorithm for Data Compression"的文章。这位程序员的初衷很简单:找到一种更高效的方式来压缩数据。他没有想到,三十年后,他发明的Byte Pair Encoding(BPE)算法会成为让ChatGPT、Claude、LLaMA等大语言模型理解人类语言的第一道关卡。

当我们在聊天框中输入"strawberry"这个词时,模型看到的并不是这九个字母,而是被切分成[“straw”, “berry”]两个token。这个看似简单的切分过程,却深刻影响着模型能否正确回答"strawberry中有几个r"这样的问题——而这正是2024年困扰整个AI社区的著名"草莓问题"的根源。

Tokenization:模型眼中的世界

任何大语言模型都无法直接处理原始文本。它们需要先将连续的字符序列切分成离散的单元,这些单元被称为token。一个token可以是完整的单词(如"hello")、单词的一部分(如"un"和"##able")、单个字符,甚至是字符的字节表示。

这种切分绝非简单的"切蛋糕"。它决定着模型能"看到"什么、如何"理解"语言,以及最终能产生什么样的输出。一个糟糕的tokenizer会让模型在处理数字时迷失方向,会让非英语用户付出更高的API调用成本,会让模型在拼写检查时表现糟糕。

从信息论的角度看,tokenization本质上是一种有损压缩。原始文本包含的字符级信息被映射到一个有限的词汇表中,不可避免地丢失某些细节。比如,当"strawberry"被编码为[“straw”, “berry”]时,单个字母’r’的位置信息就被隐藏在token内部了。这就是为什么大模型可以写出优美的诗歌,却可能数不清一个单词中有多少个特定字母。

三大主流算法的博弈

现代大语言模型几乎都采用子词分词(Subword Tokenization)策略。这种策略在词级别和字符级别之间找到了平衡:高频词保持完整,低频词被拆分成更小的单元。在这个框架下,BPE、WordPiece和Unigram成为三种主流实现方案。

Byte Pair Encoding:从压缩到分词

BPE的核心思想极其朴素:找到文本中出现最频繁的相邻字符对,把它们合并成一个新的单元,然后重复这个过程直到达到目标词汇量。

假设我们有一个简单的语料库:("hug", 10), ("pug", 5), ("pun", 12), ("bun", 4), ("hugs", 5)。BPE的训练过程如下:

初始状态,每个词被拆分成单个字符:("h" "u" "g", 10), ("p" "u" "g", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "u" "g" "s", 5)

统计所有相邻字符对的频率。在这个例子中,("u", "g")出现在"hug"、“pug"和"hugs"中,总共20次,是最频繁的对。于是我们学习第一条合并规则:("u", "g") -> "ug"

词汇表变为:["b", "g", "h", "n", "p", "s", "u", "ug"]

语料库变为:("h" "ug", 10), ("p" "ug", 5), ("p" "u" "n", 12), ("b" "u" "n", 4), ("h" "ug" "s", 5)

接下来,("u", "n")出现16次(在"pun"和"bun"中),成为下一个合并目标。这个过程持续进行,直到词汇表达到预设大小。

OpenAI在GPT-2中引入了一个关键改进:字节级BPE。他们不再以Unicode字符为基本单元,而是以字节(共256种可能)为起点。这意味着模型可以处理任何Unicode文本,而不会遇到"未知字符"的问题——因为任何字符都能表示为字节序列。

WordPiece:似然最优的贪婪选择

WordPiece与BPE的训练过程相似,但合并决策的依据不同。BPE选择频率最高的字符对,而WordPiece选择能让训练数据似然增加最多的字符对。

具体来说,WordPiece使用以下评分公式:

$$\text{score}(A, B) = \frac{\text{freq}(AB)}{\text{freq}(A) \times \text{freq}(B)}$$

这个公式的设计直觉是:如果两个子单元经常一起出现,但各自单独出现的频率较低,那么合并它们更有价值。相比之下,即使("un", "##able")这个对出现很频繁,但由于"un"和”##able"各自在许多其他词中也经常出现,它们就不一定会被优先合并。

WordPiece的另一个显著特点是其贪心最长匹配的分词策略。给定一个词,算法从左到右寻找能匹配的最长子词。比如"unhugging"会被分解为:

  1. 找到最长匹配:"un"
  2. 剩余部分:"hugging",找到最长匹配:"##hug"
  3. 剩余部分:"##ging",继续分解…

最终结果可能是:["un", "##hug", "##g", "##ing"]

BERT系列模型(BERT、DistilBERT、MobileBERT等)都使用WordPiece。

Unigram:从大到小的概率剪枝

Unigram采取了与BPE和WordPiece截然相反的策略:从一个巨大的初始词汇表开始,逐步删除"贡献最小"的token。

假设初始词汇表包含一个词的所有可能子串。对于词"unhug",初始词汇表可能包含:["u", "n", "h", "g", "un", "nh", "hu", "ug", "unh", "nhu", "hug", "unhu", "nhug", "unhug"]

Unigram的核心是概率语言模型。每个token被赋予一个概率,等于其频率除以所有token频率之和。给定一个词,Unigram计算所有可能分词方案的概率,选择概率最高的那个。

根据Unigram模型,一个分词方案的概率等于各token概率的乘积:

$$P([t_1, t_2, ..., t_k]) = \prod_{i=1}^{k} P(t_i)$$

由于每次乘法都会让概率变小(每个概率都小于1),分词方案使用的token越少,总体概率往往越高。这符合直觉:我们希望用尽可能少的token来表示一个词。

在训练过程中,Unigram计算每个token对训练数据总似然的贡献,删除那些贡献最小的token。这个过程持续进行,直到词汇表缩减到目标大小。

SentencePiece库实现了Unigram算法,被T5、ALBERT、mBART、XLNet等模型采用。SentencePiece的一个重要创新是将空格也视为特殊字符(通常表示为),这使得分词过程完全可逆,不需要额外的预处理步骤。

三种算法的本质差异

维度 BPE WordPiece Unigram
训练方向 从小到大 从小到大 从大到小
合并依据 频率最高 似然增益最大 删除似然损失最小
分词策略 按合并规则顺序 贪心最长匹配 Viterbi最短路径
概率支持 有(可采样多种分词)
典型模型 GPT系列、LLaMA BERT系列 T5、ALBERT

Unigram的一个独特优势是其概率特性允许多种分词方案。在训练时,模型可以采样不同的分词方式作为数据增强;在推理时,可以通过集成多种分词的结果来提升鲁棒性。

Tokenization如何影响模型能力

Tokenizer的选择绝非简单的工程决策,它深刻影响着模型在各类任务上的表现。近年来,研究者们发现了一些令人惊讶的现象。

算术推理:数字应该怎么切?

2024年的一项研究系统性地探讨了tokenization对大模型算术能力的影响。研究发现,数字被如何tokenize会显著影响模型的计算准确率。

GPT-3.5和GPT-4采用的是多位数字tokenization:每个1-3位的数字都是一个独立的token。比如"12345"会被分成[“12”, “345”]或[“123”, “45”](取决于具体的切分边界)。

相比之下,LLaMA和PaLM采用单位数字tokenization:每个数字都是一个独立的token。“12345"被分成[“1”, “2”, “3”, “4”, “5”]。

研究表明,单位数字tokenization在算术任务上表现更好。原因在于:当数字被拆分成单个数字时,模型可以学习类似于人类"竖式计算"的算法,逐位进行加法或乘法。而当数字被分成多位token时,模型需要记忆大量的数字对组合结果,这更像是"背诵乘法表"而非真正理解计算。

更令人惊讶的是,研究者发现通过在数字中插入逗号来改变tokenization方式(如将"12345"写成"1,2,3,4,5”),可以让模型的算术准确率提升数倍。这种现象被称为从左到右 vs 从右到左tokenization的差异。

多语言处理:隐性的不公平

2023年的一项研究揭示了一个令人担忧的事实:tokenizer在处理不同语言时存在显著的不公平性。同一段文本翻译成不同语言后,其token数量可能相差高达15倍。

以GPT-4的tokenizer为例,对于同样的语义内容:

  • 英语:约100 tokens
  • 中文:约150-200 tokens
  • 阿拉伯语:约200-250 tokens
  • 印地语:约300-400 tokens

这种差异意味着:

  1. 成本不平等:非英语用户需要支付更高的API调用费用
  2. 延迟不平等:更长的token序列意味着更长的处理时间
  3. 上下文不平等:同样的上下文窗口,非英语用户能放入的内容更少

GPT-4o的o200k_base tokenizer在这方面做了显著改进。其词汇量从cl100k_base的约100K扩展到约200K,增加了大量非英语语言的专用token。实测表明,对于中文文本,o200k_base比cl100k_base平均减少约30-40%的token数量。

字符级任务:Strawberry问题

“strawberry中有几个r?“这个问题在2024年引发了广泛讨论。许多先进的大模型给出了错误答案,声称只有两个r(忽略了berry中的r)。

问题的根源正是tokenization。在大多数tokenizer中,“strawberry"被分成[“straw”, “berry”]两个token。模型看到的是这两个整体,而不是内部的字母组合。当被问及字母数量时,模型实际上是在"猜测"token内部的结构,而非真正"看到"每个字母。

类似的问题还出现在:

  • 拼写检查:模型可能无法识别拼写错误
  • 字母排序:模型可能给出错误的排序结果
  • 字符串操作:模型在处理特定的字符级任务时表现不佳

这揭示了一个深层矛盾:子词tokenization牺牲了字符级信息的可见性,换取了序列长度的压缩效率

词汇量:大小之辩

词汇表的大小是一个关键的设计参数,需要在多个因素之间权衡。

小词汇表(如32K)的优势:

  • 模型嵌入层参数更少
  • 每个token获得更充分的训练
  • 内存占用更低

小词汇表的劣势:

  • 序列长度更长(更低的压缩效率)
  • 更多"罕见词"被拆分成碎片
  • 推理时计算步数更多

大词汇表(如100K-200K)的优势:

  • 更高的压缩效率
  • 更短的序列长度
  • 更好的多语言支持

大词汇表的劣势:

  • 嵌入层参数量显著增加
  • 某些token训练不足
  • 搜索空间更大

经验法则显示,英语文本中,1个token大约对应4个字符或0.75个单词。这意味着一个包含1000个单词的英文段落,大约需要1300-1500个token。

对于编程语言,token效率存在显著差异。一项研究分析了19种编程语言,发现从最高效到最低效存在2.6倍的差距。简洁的语言(如APL、J)每行代码只需要更少的token,而冗长的语言(如Java)则需要更多。

Tokenizer的偏见问题

Tokenizer不仅仅是技术工具,它还携带着文化和语言的偏见。

语料偏见

Tokenizer的训练数据决定了哪些子词会被纳入词汇表。如果训练语料以英语为主,英语单词更有可能被完整保留,而非英语词汇则更可能被拆分成更小的单元。

一项研究发现,即使使用了多语言训练语料,tokenizer仍然会表现出对"优势语言"的偏好。这是因为合并算法(无论是BPE、WordPiece还是Unigram)都是基于统计频率的,语料中占比更大的语言自然会产生更多的高频token。

域适应问题

当模型应用于特定领域(如医学、法律、编程)时,通用tokenizer可能表现不佳。专业术语可能被过度拆分,导致模型难以学习这些概念。

一个经典的例子是医学文献中的"hypertension”(高血压)。在通用tokenizer中,这个词可能被分成[“hyper”, “tension”]或更小的碎片,而一个医学校准的tokenizer可能会将其作为一个完整的token保留。

解决方案

针对这些问题,研究者提出了几种方案:

  1. 语言特定tokenizer:为每种语言训练专门的tokenizer,然后合并词汇表
  2. 领域适应tokenizer:在领域语料上继续训练或从头训练tokenizer
  3. 词汇表扩展:保留通用tokenizer,添加特定领域的专用token
  4. 均衡训练:在训练tokenizer时,对低资源语言进行过采样

无Tokenizer的未来?

2024年底,Meta AI发布了Byte Latent Transformer(BLT),这是第一个在规模上匹敌传统tokenization-based LLM的无tokenizer架构。

BLT直接在原始字节序列上操作。它将字节序列切分成动态的"patch”,每个patch可以包含不同数量的字节。这种设计带来了几个优势:

  1. 完全消除tokenizer偏见:任何语言的字节表示都是公平的
  2. 无需词汇表:不会有"未知词"的问题
  3. 更好的字符级任务表现:模型直接看到每个字节
  4. 自适应计算:复杂的文本段落可以使用更短的patch,获得更细粒度的处理

实验显示,BLT在字符级任务(如处理噪音输入、低资源语言翻译)上显著优于同等规模的tokenization-based模型。更重要的是,BLT证明了字节级模型可以在不牺牲效率的情况下达到与传统模型相当的性能。

在此之前,Google的CANINE(Character Architecture with No tokenization In Neural Encoders)也尝试了字符级输入,但由于计算效率问题未能大规模应用。BLT的创新在于引入了动态patch机制,实现了计算效率和字符级精度的平衡。

工程实践指南

如果你正在训练或微调一个大语言模型,tokenizer的选择和配置是需要认真考虑的环节。

如何选择算法?

BPE适合大多数通用场景,尤其是英语为主的任务。它的实现简单,训练速度快,被广泛验证。

WordPiece在处理带有丰富词缀的语言(如德语、芬兰语)时可能有优势,因为它倾向于保持词根的完整性。

Unigram在需要多语言支持或需要概率采样的场景下更合适。它的概率特性也为某些下游任务提供了灵活性。

词汇量应该设多大?

对于英语为主的单语模型,32K-50K是一个合理的起点。

对于多语言模型,建议至少100K,语言越多词汇量应该越大。

对于特定领域模型,可以在通用tokenizer基础上扩展,添加领域专用token,而不是从头训练。

训练数据应该怎么选?

理想情况下,tokenizer的训练数据应该与模型预训练数据保持一致的分布。如果模型要处理多语言,训练数据应该覆盖所有目标语言,并根据实际使用比例调整采样权重。

如何评估Tokenizer质量?

常用的评估指标包括:

  1. Fertility:平均每个词被分成多少个token,越低越好
  2. 压缩率:原始字节数与token数的比值
  3. 罕见词处理:低频词被拆分的程度
  4. 语言公平性:不同语言之间fertility的差异

需要注意的是,这些内在指标并不总能预测下游任务性能。最终还是要通过实际任务来验证。

结语

Tokenizer是大语言模型的"眼睛”,它决定了模型如何感知语言世界。从Philip Gage的数据压缩算法到今天的Byte Latent Transformer,tokenization技术走过了三十年的演进历程。

这三十年里,我们学会了用频率来构建词汇表,学会了在效率和精度之间权衡,学会了处理多语言的复杂性。但我们也在"strawberry问题"中看到,这个看似简单的预处理步骤,仍然隐藏着未被完全理解的深层问题。

当Meta的BLT证明了无tokenizer架构的可行性时,我们或许正站在另一个转折点上。未来的大语言模型,也许不再需要依赖一个固定的词汇表来理解语言——它们可能会像人类一样,从最基础的字符开始,构建对语言的完整认知。

在那之前,理解tokenizer如何工作,仍然是深入理解大语言模型的关键一步。因为当我们问一个模型"strawberry中有几个r"时,答案不仅取决于模型的推理能力,更取决于它在tokenization阶段被"允许"看到什么。


参考资料

  1. Gage, P. (1994). A New Algorithm for Data Compression. C Users Journal, 12(2).
  2. Sennrich, R., Haddow, B., & Birch, A. (2016). Neural Machine Translation of Rare Words with Subword Units. ACL 2016.
  3. Kudo, T., & Richardson, J. (2018). SentencePiece: A simple and language independent subword tokenizer and detokenizer for Neural Text Processing. EMNLP 2018.
  4. Petrov, A., et al. (2023). Language Model Tokenizers Introduce Unfairness Between Languages. arXiv:2305.15425.
  5. Singh, A., & Straber, D. (2024). Tokenization counts: the impact of tokenization on arithmetic in frontier LLMs. arXiv:2402.14903.
  6. Pagnoni, A., et al. (2024). Byte Latent Transformer: Patches Scale Better Than Tokens. arXiv:2412.09871.
  7. Hugging Face LLM Course - Tokenization Chapter
  8. OpenAI tiktoken documentation