Lesson 0002 · Phase 1 地基 · 约 40 分钟
Tokenizer:大模型的第一道门
上一课的 Q&A 里你说知道了"token 是砖"。本课带你看砖是怎么烧出来的——这是理解一切"模型怪癖"(数不清 r、算不对数、对空格敏感)的源头,也是后面读任何模型 config 时 vocab_size 一栏的答案。
一、子词的三难权衡
把文本变成 id,有三种切法,各有死穴:
| 切法 | 词表大小 | 序列长度 | 死穴 |
|---|---|---|---|
| 字符级 character | 极小(几百) | 极长 | "tokenizer" 要 9 个 token,语义被稀释,上下文窗口被浪费 |
| 词级 word | 爆炸(英语 50 万+) | 短 | OOV:新词、错拼、"GLM-4.5" 都表示不了;cats / cat 还要各学一遍 |
| 子词级 subword | 可控(10 万级) | 适中 | 基本没有——这就是为什么全行业都用它 |
子词的直觉:高频词保持完整,低频词拆成有意义的碎块。unbelievable → un + believ + able,每个碎块都在别的词里见过——词表不用大,却什么词都能拼出来。
二、BPE:让词表自己"长"出来
BPE(Byte Pair Encoding) 的核心只有一句话:反复合并语料中频次最高的相邻对。它分两个阶段:
- 训练(学合并表):把语料拆到字符 → 数每一对相邻符号的出现次数 → 合并最高频的那对 → 重复,直到词表达到目标大小。产物是一张有序的合并规则表。
- 编码(用合并表):新文本先拆成字符,然后按训练时的合并顺序逐条应用规则——顺序就是优先级。
newest 和 widest 会共享什么子词?——带着预测看演示,记忆效果翻倍。棕色的 </w> 是词尾标记,作用是让"er"和"词尾的 er"可以被区别对待。
现代 LLM 用的是它的工业变体 byte-level BPE:先把文本转成 UTF-8 字节流(任何语言、任何 emoji 都不过是 1~4 个字节),再在字节上跑 BPE。好处只有一个但足够致命:不存在 OOV——凡是能输入的文本,必有 token 表示。
三、动手:用 GLM-4.5 的真实词表切文本
下面这条命令会从 ModelScope 下载 GLM-4.5 的 tokenizer.json(约 15MB,首次后缓存),加载它的真实生产词表,切分几个精心挑过的样本:
conda activate py310_qwenpaw
cd E:\MyWork\AI
python scripts\tokenizer_play.py
切自己的文本:
python scripts\tokenizer_play.py "DeepSeek-V3 是 671B-A37B 的 MoE 模型"
strawberry被切成几个 token?字母 r 出现在 token 的哪个位置?3.1415926被切碎成什么?数字之间有规律吗?- Python 代码样例里的缩进空格变成了什么?(提示:找
Ġ标记,它是 byte-level BPE 对空格的记号) - 数一数:这句中文按"字"算多少字、按 token 算多少个?
四、四个著名的 tokenizer 怪癖
1. 为什么模型数不清 strawberry 里有几个 r
模型看到的不是字母,是 token id。如果 strawberry 是一整个 token,那么"第 3 个字母是 r"这种信息只以压缩形式藏在嵌入向量里,模型需要学会"从 token 反推拼写"——这本质上是学了一门隐形的拼写课。所以 2024 年各家模型纷纷翻车,而训练量上去后大幅好转:机制原因还在,但已经被数据硬灌会了。
2. 数字为什么切得稀碎
3.1415926 可能被切成 3、.、14、159、2——数字串的切分方式既不稳定也不保序。数值和 token 对不上齐,位值规律就难学。这是部分模型"算术弱"的架构外原因之一(对策:强制数字单字切分,一些新模型已采用)。
3. 空格也是 token 的一部分
代码缩进 可能是专用 token;句子里的空格挂在后词开头(Ġworld)。所以 prompt 里多打一个空格、用不同的空白风格,都等于换了输入——偶尔会引起性能波动,不是玄学,是切分变了。
4. 中文为什么 1 字 ≈ 1~2 token
BPE 按频率合并,中文单字频率高、稳定,容易成为独立 token;二字词是否合并取决于语料量与词表预算。词表大小是各家的重要调度项:GLM-4.5 约 15 万、Kimi K2 是 16 万,而早期的 Llama 2 只有 3.2 万——同样的中文文本,Llama 2 要切出多得多的 token,推理成本直接翻倍。词表大小 × 上下文长度,共同决定"钱"。
五、检索练习
六、本周深读任务(一手来源)
- 动手(15 分钟):跑通
tokenizer_play.py,完成第三节的 4 个观察任务,把结果带回来——我们对照真实切分逐条复盘四个怪癖。 - 周末主看(可选加餐,2 小时):Karpathy "Let's build the GPT Tokenizer"(Zero to Hero 系列最硬核的一集)——从零实现一个工业级 tokenizer,与本课的模拟器互相印证。
- 定义邀请(1 分钟):用你自己的话给 术语表写一条 BPE 的定义——合格即转正,本课术语就齐了。
脚本跑不通、切分结果看不懂、或者对某个怪癖想深挖——直接问我,我是你的老师。