为什么中文更「贵」?
本课一问:为什么中文更「贵」?
这是第 3 课旁边的岔路。这一课先不碰:词表该多大(第 4 课)。只回答两件事——BPE 的最小单元为什么是字节,以及这个选择怎样让没学过中文的词表把中文切得很碎。
BPE 从「最小单元」出发
第 3 课的第一步:「把语料拆成最小单元,作为初始词表」。最小单元选什么?最自然的答案是字符。先记下贯穿例句的账:「小明把苹果给了小王」9 个字、27 个 UTF-8 字节,GPT-2 切成 21 个 token,Qwen3.8 切成 5 个——同样是字节级 BPE,差了 4.2 倍。这一课回答差在哪。
朴素的想法:以字符为最小单元
- ① 朴素方案
- ② 它在哪失败
- ③ 改进方案
Sennrich 2015 的 BPE 就是这么做的:初始词表 = 语料里出现过的所有字符。对英文这没问题,字母就几十个;对中文和几百种文字的混合语料,麻烦来了:
- Unicode 收录的字符在 2026-09 发布的 18.0 版里已有 172,808 个;全部放进初始词表,词表还没开始合并就已经很大;
- 只收语料里出现过的字,词表小了,但一遇到训练时没见过的字就只能记成 UNK。我们的项目语料实测:训练集里有 4,073 个不同字符,验证集里仍有 83 种字训练集从没出现过,占验证集字次 0.42%。
换个最小单元:字节。任何文字在计算机里都是 UTF-8 字节串,字节只有 256 种取值。以这 256 个字节为初始词表:
- 词表起点固定是 256,和语言无关;
- 任何输入都能表示,永远不会出现 UNK——最坏情况是一个字节一个 token;
- 代价:一个常用汉字在 UTF-8 里是 3 个字节,如果词表没学到把这 3 个字节合起来的规则,这个字就要 2 到 3 个 token。
GPT-2(2019)用的就是这个方案,Qwen3.8 也是。
透视:同一串字节,两个词表怎么切
本课在演进图里的位置:第二代,字节级 BPE。
- 解决了不用训练,任何文字都能编号。卡在码点从 0 排到 1,114,111,embedding 表得开 1,114,112 行,是 Qwen3.8 实际 248,320 行的 4.5 倍;而且一个字一个 ID,序列一点不缩短。
- 解决了字符集封闭,词表小。卡在序列最长:209 字的段落按字切要做 43,681 次注意力打分,是 Qwen3.8 子词切分(106 个 token)的 3.9 倍。
- 解决了一个词一块,序列短。卡在词是开放集合:我们的语料按空白和标点切出 70,310 种块,94.8% 只出现过一次;验证集里连训练集没见过的字都有 83 种——含它们的词只能记成 UNK。
- 解决了按频次反复合并相邻对:常见的整块、罕见的拆碎,词表大小由合并次数控制。卡在初始单元是字符:要覆盖全部 Unicode,基础词表就超过 13 万(GPT-2 论文 §2.2);只收见过的字,我们的验证集照样缺 83 种字。
- 解决了初始词表就是 256 个字节,任何文字都能编码,永远不出 UNK。卡在词表没学过的语言会被切碎:同义的中文段落,GPT-2 切 461 个 token,Qwen3.8 切 106 个,差 4.3 倍;同义英文段落两者一样多。
- 解决了中文常用字串整块进词表:「我喜欢机器学习」只要 2 个 token(GPT-2 要 17 个)。各家词表:DeepSeek-V3 129,280 · Qwen3 151,936 · GLM-5.3 154,880 · Kimi K3 163,840 · Qwen3.8 248,320。卡在两头各一张 V × d 的表:2 × 248,320 × 5,120 = 2,542,796,800 个参数,占 Qwen3.8 的 9.2%;同样的词表搬到我们 d = 256 的小模型上,embedding 占 95.3%。
- 解决了ID 只是行号,取出一行 5,120 维向量;one-hot 乘矩阵与查表等价,但查表只拷现成的数。卡在表里的 1,271,398,400 个数(输入端一张表)从哪来?人填不完,也不知道每一维该是什么意思。
- 解决了用「预测下一个 token」的 loss 端到端训练,用法相近的 token 被推到相近的位置。卡在只在出现时才被推:我们的项目里一个 batch 8,192 个位置,平均只出现 1,453 个不同 token;罕见 token 学得少——MiniMax 的「嘉祺」在后训练里被推偏,输出层那一行与原来的余弦只剩 0.329。
- 解决了维度越高,每个 token 能装的信息越多。卡在参数按 d² 涨:我们的模型 d 从 128 到 256,总参数 1,066,112 → 3,688,704,val loss 4.776 → 4.641(d = 256 这一档是参照 run ref_baseline,与项目基线同配置同种子;基线记录的 4.626 与它之差是重跑波动,见 C14);没有公式能给出「最优的 d」。
先看文字在 UTF-8 里是几个字节,再看 GPT-2 和 Qwen3.8 这两个真词表,把同一串字节切成了什么(B 部分默认就是贯穿例句)。
在 B 部分切到「今天天气真好」:6 个字、18 个字节。GPT-2 用了 10 个 token,其中「今」被切成 2 块(E4 BB 与 8A)、「天」恰好是 1 块;Qwen3.8 只用 3 个:「今天」「天气」「真好」各是词表里的一项。
差别不在中文,而在词表学到了哪些合并。GPT-2 的训练语料以英文为主,中文字节对的频次不够高,轮不到被合并;Qwen3.8 的 24.8 万词表学了大量中文合并。同义的两段文字:中文段落 209 字,GPT-2 切 461 个 token、Qwen3.8 切 106 个;同义英文段落两者都是 149 个——英文上两者打平,中文上差 4.3 倍。
这就是成本:API 按 token 计费,上下文窗口按 token 计量。同一段中文,用 GPT-2 的词表要花约 4.3 倍的 token,钱和窗口都按这个倍数消耗。这也是 Qwen、GLM、DeepSeek 都训练自己的大词表的原因——它们官方配置里的词表(embedding 行数)分别是:Qwen3.8 248,320、GLM-5.3 154,880、DeepSeek-V3 129,280,而 GPT-2 是 50,257。
常见误解一:「显示出 � 是 bug」。 单独一个字节 token 常常只是半个汉字,不是合法的 UTF-8,单独解码就显示成 �。凑齐同一个字的几个 token 才能还原。实验课里的橙色虚线框,就是把「凑齐一个字」的几个 token 圈在一起。
常见误解二:「一个汉字固定是 3 个 token」「ASCII 字符 1 字节 1 token」。 字节数只是上限。GPT-2 切「今天天气真好」时,一个字有的是 1 个 token、有的是 2 个;英文字母同样会被合并,「apple」在两个词表里都是 1 个 token。扩展区汉字(如 𠀀)和 emoji 在 UTF-8 里是 4 个字节,也不是 3 个。
🔍 GPT-2 为什么选字节:原文怎么说
GPT-2 论文 §2.2「Input Representation」:参考实现的 BPE 在 Unicode 码点上操作,要覆盖所有 Unicode 字符串,就得把全部码点放进基础词表,「在加入任何多字符 token 之前,基础词表就超过 130,000」,而当时常用的 BPE 词表只有 32,000 到 64,000;字节级 BPE 的基础词表只需要 256。它同时规定不跨字符类别合并(第 3 课的 Dig)。(本地 PDF)
一个字几个字节:UTF-8 的分段规则
一个字符占几个字节,完全由它的码点落在哪一段决定。点每一段看它的意思和例子:
试三件事: ① 在 A 部分输入「é 的两种写法」:看起来一样的两个 é,一个是 2 字节的单个码点,一个是「e + 组合重音」共 3 个字节——Qwen3.8 分词前会先做 NFC 规范化,把后者统一成前者;② 在 B 部分切到「a TAB b CRLF c」:Qwen3.8 把 TAB 和后面的 b 合成了一块,CRLF 也是一块,GPT-2 则一个一个切;③ 切到「价格 NBSP 100 NBSP 元」,看 Qwen3.8 怎样把 100 一位一位切开。
字节级 BPE 的账
- 它解决什么问题:让一个词表覆盖任意语言、任意字符,永远不出现 UNK,同时基础词表很小。
- 数学上为什么可能有效:UTF-8 把每个码点编成 1–4 个字节,256 个字节值覆盖全部字节串 证据等级 · 数学可证明 在写明的前提下可以严格推导出来,不依赖实验。只要前提成立,换数据、换规模仍然成立。 本条UTF-8 编码定义,RFC 3629 出处RFC 3629 ↗需联网 ;所以「永不缺字」可证明,「一个汉字最多 3 个 token(基本平面内)」也可证明。
- 实验上为什么最后选了它:同样是字节级 BPE,中文 token 数差几倍,取决于训练语料里中文的比例——同义段落 GPT-2 461 对 Qwen3.8 106 是对真分词器的测量 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条两个真分词器离线切分同一段文字;只代表这两个词表 出处c1-tokenize.json ↗需联网 ;「中文税」在 5 个商用分词器上的对比来自极客公园的实测 证据等级 · 实验验证 由对比实验得出的经验结论,只在出处写明的模型、数据和规模下成立。换了条件可能不再成立,引用时要带上实验设置。 本条22 段平行文本;不同模型版本结果不同,引用要带版本 出处极客公园 2026-05 ↗需联网 。
一句话、回到主线、你的提问
一句话: 字节级 BPE 永远不缺字,但一个没学过中文合并的词表,会把一个汉字拆成最多 3 个字节 token——中文的「贵」来自词表,不来自中文本身。
回到主线
Qwen3.8 用 24.8 万的大词表换来了中文的低 token 数。那词表是不是越大越好?它的代价记在哪里?第 4 课:词表该多大?
你的提问
你可能会问:「我们自己的分词器只在繁体古白话上训练,切简体现代文会怎样?」 在第 3 课的真实日志压轴输入框里切「小明把苹果给了小王。」,虚线框就是它没学过的字;实验课里还能把同一句交给三个分词器并排比。