从零手写大模型 · 推理篇 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(分词器)

← 返回文章列表