在深入 Prompt Engineering、RAG、微调等高级话题之前,有一项最基础但至关重要的技术常常被忽视------Tokenization(分词算法) 。它是所有大语言模型(LLM)处理文本的第一道工序,决定了模型如何看待文字,并深刻影响着推理成本、上下文长度、模型效果以及后续所有环节的设计。
本文从"是什么、为什么需要它、底层怎么运作、与上层概念有何关联"四个维度,系统拆解 Tokenization 的核心原理与主流算法。
一、Tokenization 是什么?
Tokenization 是将原始文本(人类可读的字符串)切分成模型词汇表中存在的最小单元(Token) ,并将每个 Token 映射为一个整数 ID 的过程。这个整数 ID 就是后续 Embedding 层的输入索引------模型看到的不是文字,而是一串数字。
例如,对于句子 "Hello, world!":
- 一个简单的分词器可能输出:
["Hello", ",", " world", "!"] - 一个 BPE 分词器可能输出:
["Hello", ",", "Ġworld", "!"](Ġ表示空格) - 对应的 ID 可能是:
[15496, 11, 995, 0]
关键点:Tokenizer 决定了 LLM 看到的最小语义单位是什么。它既不是"按单词切分"那么粗,也不是"按字符切分"那么细,而是介于两者之间的**子词(subword)**粒度。
二、为什么需要 Tokenization?
-
Transformer 无法处理字符串
神经网络只能处理数字,所以必须把文本变成 ID 序列,才能输入模型。
-
平衡词表大小与 OOV(未知词)问题
- 按单词切分:词表巨大(可能数百万),且遇到新词(OOV)无法处理。
- 按字符切分:词表极小(几十个),但序列极长,模型难以学习语义。
- 子词切分是折中方案:词表控制在几万到几十万,同时能通过组合子词表示任何新词。
-
影响推理成本和上下文长度
Token 切得越碎,同样文本产生的 Token 数越多,推理越慢,占用的上下文窗口也越多。
-
影响模型效果
不合理的切分会破坏语义边界(例如把
"unhappiness"切成"un" + "happ" + "iness"就比"un" + "happiness"差),从而影响模型对语言的理解。
三、三种主流 Tokenization 算法
1. BPE(Byte-Pair Encoding)
核心思想:从字符级别开始,统计最频繁共现的相邻字符对,合并成新的子词,反复迭代。
训练流程:
- 初始化词表:所有字符(或字节)作为基础符号。
- 统计训练语料中所有相邻符号对的出现频率。
- 合并频率最高的那个符号对,生成一个新符号,加入词表。
- 在语料中替换掉所有出现过的该符号对。
- 重复步骤 2-4,直到词表达到预设大小(如 GPT-2 的 50,257)。
例子 :假设训练语料中有大量 "low" 和 "lower",频率统计发现 "l" + "o" 出现最多,合并成 "lo";之后 "lo" + "w" 合并成 "low";再后来 "low" + "er" 合并成 "lower"。
关键特点:
- 频率驱动:只关心"谁出现得多",不关心语义是否合理。
- 词表大小可控:通过预设词表大小精确控制。
- 擅长处理罕见词:罕见词会被拆成更小的子词组合。
- 缺点 :可能合并出无语义单元(比如
"the" + "re"虽然频率高,但合并成"there"并不总是语义完整)。
进阶:Byte-level BPE(字节级 BPE)
GPT-2 引入的改进:直接在 UTF-8 字节上做 BPE,而不是在 Unicode 字符上做。好处是:
- 词表基础符号只有 256 个(一个字节的所有可能取值)。
- 可以编码任何 Unicode 字符(包括 emoji、罕见符号),不存在 OOV。
- 缺点是某些字符会被拆成多个字节,序列变长。
代表模型:GPT-2 / GPT-3 / GPT-4、RoBERTa、Codex 等。
2. WordPiece
核心思想 :与 BPE 类似,但合并标准不是"频率",而是最大化训练数据的似然概率。
训练流程:
- 同样从字符级词表开始。
- 对每一对相邻符号,计算如果合并它们,训练语料的语言模型概率会增加多少。
- 选择使语言模型概率提升最大的那个合并。
- 重复直到词表达到预设大小(如 BERT 的 30,522)。
似然增益的计算 (简化理解):对于相邻符号 (a, b),如果合并成 ab,那么训练语料中所有出现 (a, b) 的地方都会被替换为 ab。这样词表增加了一个符号,但语料的总长度缩短了。WordPiece 计算这种替换导致的训练数据概率变化,选择增益最大的合并。
关键特点:
- 概率驱动:生成的子词通常更符合语言习惯,因为它是从语言模型的角度出发优化的。
- 子词前缀标记 :使用
##表示该子词是前一个词的延续。例如"tokenization"会被切成["token", "##ization"]。 - 词表更"干净":相比 BPE,WordPiece 产生的子词通常语义更完整。
代表模型:BERT、DistilBERT、ALBERT 等。
3. SentencePiece
核心思想:直接从原始文本(包括空格)进行训练,不依赖空格分词,对中文、日文等无空格语言友好。
关键设计:
- 不依赖预分词:BPE 和 WordPiece 通常需要先按空格把文本切成单词,再在单词内部做子词合并。SentencePiece 直接在原始字符流上训练,把空格也当作一个普通字符。
- 空格用特殊符号表示 :通常把空格映射为
▁(U+2581),这样模型能区分"词首"和"词中"。 - 支持两种子词算法 :
- BPE(与上面类似,但直接在原始字符流上运行)
- Unigram(一种基于概率的删除算法)
Unigram 算法:与 BPE 的"从少到多"合并相反,Unigram 是"从多到少"删除:
- 初始化一个很大的词表(例如包含所有可能的子词组合)。
- 用 EM 算法估计每个子词的概率。
- 计算如果删除某个子词,训练语料的似然损失最小(即该子词最不重要)。
- 删除这个子词。
- 重复步骤 2-4,直到词表缩小到预设大小。
关键特点:
- 语言无关:不需要预分词,适合中文、日文、韩文等无空格语言。
- 端到端:训练和使用都是端到端的,不需要额外的分词器。
- 覆盖最广:Llama、T5、Gemma、Mistral 等现代模型几乎都用 SentencePiece(或它的变体)。
代表模型:Llama 系列、T5、Gemma、Mistral 等。
四、核心对比与记忆点
| 算法 | 合并/删除标准 | 是否依赖预分词 | 代表模型 | 关键特点 |
|---|---|---|---|---|
| BPE | 频率最高 | 通常需要预分词(字节级 BPE 不需要) | GPT 系列、RoBERTa | 简单高效,词表可控;可能产生无语义子词 |
| WordPiece | 似然增益最大 | 需要预分词 | BERT、DistilBERT | 概率最优,子词更符合语言习惯;用 ## 标记 |
| SentencePiece | 支持 BPE 和 Unigram | 不需要预分词 | Llama、T5、Gemma | 语言无关,空格用 ▁ 表示;现代模型主流选择 |
一句话总结 :BPE 靠频率,WordPiece 靠概率,SentencePiece 不依赖空格且覆盖最广。
五、Tokenization 如何影响上层应用?
理解 Tokenization 不仅是为了应付面试,它直接关系到大模型应用的多个关键环节:
- Prompt Engineering:中文通常 1 个汉字 ≈ 1-2 个 token,英文 1 个单词 ≈ 0.75 个 token。同样语义的中文 prompt 可能消耗更多 token,影响成本和上下文利用率。
- RAG 分块:分块时如果只按字符数切,可能会把一个子词从中间切断,影响检索质量。好的实现会参考 tokenizer 边界。
- 微调 :微调时必须使用与预训练完全相同的 tokenizer。换了 tokenizer,Embedding 层完全不匹配,模型直接崩溃。
- 推理加速:Token 数直接决定 KV Cache 大小。同样文本,token 数越少,推理越快。
- 上下文窗口 :模型说的"上下文长度 128K"指的是 128K 个 token,不是字符数。理解 tokenizer 才能准确估算能塞进多少内容。
六、总结
Tokenization 是 LLM 的地基 。它看似枯燥,却是所有高级技术的基石。选对或理解 tokenizer,能让你在优化 prompt、设计 RAG 系统、微调模型、估算成本时少走很多弯路。三种主流算法各有侧重,但现代大模型已经收敛到 SentencePiece(或字节级 BPE) 这一路线,核心趋势是语言无关、端到端、可处理任何 Unicode 字符。
掌握了 Tokenization,你就拿到了理解大模型"如何看待世界"的第一把钥匙。