从0训练LLM · 现代大模型体系 阅读 + 实验 ≈ 25 分钟 页内实验 ×1
C1 文字怎么变成数字 第 2 课

为什么不一字一个 Token,也不一词一个 Token?

切多细
切得越细,序列越长,注意力的计算量按长度的平方涨;切得越粗,词表越大,还总会遇到没见过的词。子词切分取中间。

本课一问:为什么不一字一个 Token,也不一词一个 Token?

这一课先不碰:子词表具体是怎么学出来的(第 3 课)、词表该定多大(第 4 课)。只回答「切多细」这一个取舍。

② 从已有出发

上一课留下的两个数

从已有出发 · 累计数据流 点已学环节看形状与参数
解码层

上一课:分词器把文字切成词表里的块,再把每块换成行号。贯穿例句「小明把苹果给了小王」有 9 个字:按字切是 9 块,Qwen3.8 切成 5 块(小明 / 把 / 苹果 / 给了 / 小王),GPT-2 切成 21 块。块切多大,同时决定了两个数——序列长度 T(一句话变成几个 token)和词表大小 V(一共要准备多少种块)。

T 不只是个计数:训练要处理多少 token、按 token 计费的 API 要花多少钱、上下文窗口能装下多少内容,全都按 token 数算。注意力这一步还要让每个 token 给每个 token 打分,打分次数按 T² 增长(C3 细讲)。

③ 先自己设计

两个最自然的方案:按字切,按词切

按字切,字符集是封闭的,词表很小;按词切,一句话只有几块,序列很短。选一段文字,看这两个方案各在哪个数上失败。(组件默认换成一段 209 字的段落:贯穿例句只有 9 个字,T² 的差距要在长一点的文字上才看得出来;第三个按钮就是一句短句,可以对照。)

  1. ① 朴素方案
  2. ② 它在哪失败
  3. ③ 改进方案
朴素方案按字切,或者按词切
切法token 数 T上面这段文字注意力打分 T²上面这段文字词表要多大项目语料实测遇到没见过的项目 val 实测
④ 改进到现代做法

三种切法并排:真切分

本课在演进图里的位置——两个朴素方案,一个太碎、一个太粗:

文字 → 数字的演进:每一步都被上一步的某个真数字逼出来 · 高亮 = 本课
  1. 起点 每个字符直接用 Unicode 码点当编号 最容易想到的做法
    解决了不用训练,任何文字都能编号。
    卡在码点从 0 排到 1,114,111,embedding 表得开 1,114,112 行,是 Qwen3.8 实际 248,320 行的 4.5 倍;而且一个字一个 ID,序列一点不缩短。
  2. 朴素 ① 按字切(字符级词表) 只收语料里出现过的字 本课
    解决了字符集封闭,词表小。
    卡在序列最长:209 字的段落按字切要做 43,681 次注意力打分,是 Qwen3.8 子词切分(106 个 token)的 3.9 倍。
  3. 朴素 ② 按词切 + 固定词表 早期神经机器翻译的做法(Sennrich 2015 的对照组) 本课
    解决了一个词一块,序列短。
    卡在词是开放集合:我们的语料按空白和标点切出 70,310 种块,94.8% 只出现过一次;验证集里连训练集没见过的字都有 83 种——含它们的词只能记成 UNK。
  4. 第一代 子词 BPE(以字符为初始单元) Gage 1994 压缩算法 → Sennrich 2015 用于切词
    解决了按频次反复合并相邻对:常见的整块、罕见的拆碎,词表大小由合并次数控制。
    卡在初始单元是字符:要覆盖全部 Unicode,基础词表就超过 13 万(GPT-2 论文 §2.2);只收见过的字,我们的验证集照样缺 83 种字。
  5. 第二代 字节级 BPE(256 个字节兜底) GPT-2 2019
    解决了初始词表就是 256 个字节,任何文字都能编码,永远不出 UNK。
    卡在词表没学过的语言会被切碎:同义的中文段落,GPT-2 切 461 个 token,Qwen3.8 切 106 个,差 4.3 倍;同义英文段落两者一样多。
  6. 第三代 为多语言训练的大词表 2024–2026
    解决了中文常用字串整块进词表:「我喜欢机器学习」只要 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%。
  7. 表示 ① ID → Embedding 查表 神经语言模型的标准做法
    解决了ID 只是行号,取出一行 5,120 维向量;one-hot 乘矩阵与查表等价,但查表只拷现成的数。
    卡在表里的 1,271,398,400 个数(输入端一张表)从哪来?人填不完,也不知道每一维该是什么意思。
  8. 表示 ② 随机初始化、和整个模型一起训练的 Embedding Bengio 等 2003 → 今天的 LLM
    解决了用「预测下一个 token」的 loss 端到端训练,用法相近的 token 被推到相近的位置。
    卡在只在出现时才被推:我们的项目里一个 batch 8,192 个位置,平均只出现 1,453 个不同 token;罕见 token 学得少——MiniMax 的「嘉祺」在后训练里被推偏,输出层那一行与原来的余弦只剩 0.329。
  9. 表示 ③ 向量该多宽(hidden size d) 各家自选:GPT-2 768 · Qwen3-8B 4,096 · Qwen3.8-2.4T 8,192 · Qwen3.8-27B 5,120
    解决了维度越高,每个 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」。
数字口径:码点总数按 Unicode 标准(U+0000–U+10FFFF);词表与宽度取各模型官方 config.json(anchor-model.json、frontier-models.json);token 数取真 Qwen3.8 / GPT-2 分词器的离线切分(c1-tokenize.json);语料统计、batch 覆盖、宽度扫描取项目实测(c1-tokens.json);「13 万以上」出自 GPT-2 论文 §2.2;「嘉祺」的余弦 0.329 出自 MiniMax 官方博客 2026-05-25(官方自报)。

同两个例子,三种切法(字符数、字母数由定义给出;子词一行是 Qwen3.8 与 GPT-2 真分词器的结果):

切法「今天天气真好」unbelievable好处致命伤
按字符今 / 天 / 天 / 气 / 真 / 好:6 块12 个字母:12 块字符集封闭,词表小序列最长,注意力打分数按 T² 涨
按词取决于分词工具(上面的组件用浏览器内置分词器实时切)1 块序列短词是开放集合:新词、人名、错拼永远收不完,词表爆炸,没见过的只能记成 UNK
子词(Qwen3.8)今天 / 天气 / 真好:3 块un / belie / vable:3 块常见的整块留、罕见的拆碎;词表大小可控;字节兜底,永不 UNK切法要从数据里学(第 3 课)
子词(GPT-2)10 块(大多是半个字的字节)un / bel / iev / able:4 块同上词表没学过中文合并,中文被拆得很碎

同一个「子词」思路,两个词表切出来差了三倍多:「今天天气真好」Qwen3.8 用 3 个 token,GPT-2 用 10 个(旧版课程写的「Qwen 4 个」是上一代 Qwen2.5 的数字)。子词切分只是方法,切得好不好取决于词表是在什么数据上学出来的。

⚠

常见误解:「中文模型就是一字一个 token」。 Qwen3.8 把 7 个字的「我喜欢机器学习」切成 2 个 token;GPT-2 把它切成 17 个——比字数还多。两者都不是一字一 token:token 数取决于词表学到了哪些合并,和「一个字」没有固定对应。

⑤ 极小真数字,算一次

压缩率:一个 token 平均装几个字符

衡量「切得多粗」最常用的数叫压缩率。点公式里的每一项:

压缩率(字符 / token)
= ÷
👆 公式里带下划线的每一项都可以点——点哪项,讲哪项。
数字来源:字符数按定义数码点;token 数来自真 Qwen3.8 与 GPT-2 分词器的离线预计算(src/data/precomputed/c1-tokenize.json,2026-09-26)。英文 5.48 比中文 1.97 大,不代表英文「更省」:一个汉字承载的信息通常比一个英文字母多,比较不同语言要看同义文本的 token 数(同义段落:中文 106,英文 149)。

再算一次注意力的账:同一段中文,按字切 T = 209,打分 209² = 43,681 次;Qwen3.8 切 T = 106,打分 106² = 11,236 次;GPT-2 切 T = 461,打分 461² = 212,521 次——对这段中文,GPT-2 的子词切分比按字切还贵。

👀

试三件事: ① 在上面的组件里切到「同义英文段落」,看按字符切的 T² 比 BPE 大多少倍——英文按字母切比中文按字切更吃亏;② 切到「我喜欢机器学习」,词级那一列的块数和 Qwen3.8 的 2 块谁多?③ 回头看表里词级那一行:项目环境没有中文分词器,词级的完整 UNK 率没有实测;表里给的是能实测的下界——含「训练集没见过的字」的词一定是 UNK。

⑦ 证据三问

子词为什么赢

⑧ ⑨ ⑩ 带走与下一步

一句话、下一个缺口、你的提问

📌

一句话: 切得越细,序列越长;切得越粗,词表越大还会遇到没见过的词——子词取中间:常见的整块留,罕见的拆成碎片。

下一个缺口

「常见的整块留」——谁来决定哪些字串算常见、该进词表?第 3 课:BPE 怎么学会「该怎么切」?

你的提问

C1 还没有真实提问记录。你可能会问: