从零手写大模型 · 推理篇 02 - Tokenizer(分词器)
推理篇 · 查看系列模型怎么"读懂"文字?
先从一个问题开始
你有没有想过——
你输入"猫吃鱼", 模型是怎么处理这三个字的?
它能直接看懂"猫"这个字吗?
不能。
模型只认识数字, 不认识任何文字。
所以在喂给模型之前, 所有的文字都要先变成数字。
这个"翻译官"就叫做
Tokenizer
分词器
它做什么?
一句话:
把文字变成数字
"猫吃鱼"
↓
[E5, B8, AD, ...]
↓
[Token 1, Token 2 ...]
这个过程叫 encode(编码)
反过来也可以:
把数字变回文字
这个过程叫 decode(解码)
但不是一个字一个数字
你可能以为是这样:
猫 → 1
吃 → 2
鱼 → 3
不是的。
实际上"猫吃鱼"三个字, 会变成 8 个数字。
为什么?
要从字节说起
计算机存储文字, 用的是 UTF-8 编码。
每个汉字在 UTF-8 里 占 3 个字节:
猫 → E5 B8 AD(3个字节)
吃 → E5 90 83(3个字节)
鱼 → E9 B1 BC(3个字节)
3个汉字 = 9个字节
Tokenizer 看到的, 不是"猫吃鱼"这三个字,
而是这 9 个字节。
那 BPE 是什么?
BPE 是分词器背后的算法。
它做一件事:
把经常挨在一起的字节, 合并成一个 Token。
比如:
A B C A B D A B C
发现 AB 经常在一起
→ 合并 AB 为一个新符号 X
X C X D X C
反复合并, 直到词表大小达到目标为止。
GPT-2 的词表是 50257 个 Token。
所以"猫吃鱼"为什么是 8 个?
原本是 9 个字节,
BPE 发现其中某两个字节 经常挨在一起出现,
合并了一次,
所以变成了 8 个 Token。
重要:BPE 不认识中文
这里有个关键认知——
BPE 不知道什么是汉字, 也不知道什么是英文。
它眼里只有字节:
E5 B8 AD E5 90 83 E9 B1 BC
就是一串 0 和 1 的数字。
哪两个字节经常一起出现, 就合并哪两个。
纯粹是统计,没有任何语言理解。
中文 vs 英文 的差距
"cat eats fish"
→ 3 个 Token ✅
"猫吃鱼"
→ 8 个 Token ❌
同样的意思, 中文花的 Token 是英文的 2倍多。
原因很简单:
GPT-2 用英文数据训练, 英文的字节组合大量被合并过, 中文的几乎没有。
所以用 GPT 处理中文, 又贵又慢。
两层映射
我们来捋一下整个流程:
第一层:文字 → Token ID
"猫"
↓ UTF-8 编码
E5 B8 AD(字节)
↓ BPE 查表
[Token 编号]
第二层:Token ID → 特征向量
[Token 编号]
↓ Embedding 矩阵
[0.23, -0.17, 0.85, ...]
这是一个几百维的向量, 才是模型真正能处理的输入。
经过这两层, "猫"才有了模型能理解的"样子"。
小结
今天学了三件事:
① Tokenizer 把文字变成数字
② BPE 是纯统计的合并算法
③ 中文比英文消耗更多 Token
下一期我们讲第二层映射——
Embedding
Token 编号怎么变成特征向量?
从零手写大模型 · 推理篇 02 - Tokenizer(分词器)