从0训练LLM · 现代大模型体系 导读 7 课 + 2 条岔路 + 1 节实验课 ≈ 4 小时
C1 文字怎么变成数字 章导读

文字怎么变成数字

神经网络只会算数字。这一章把一句中文变成 [T × 5120] 的向量矩阵:先切成 token,再换成词表行号,最后查表变成向量——每一步为什么这样做,都从朴素方案的失败里逼出来。
① 主线定位

这一章在整条主线的哪里

整门课围绕一条流水线:从人写的一句话,到「下一个 token 是谁」的概率。C1 是这条流水线的入口——把文字变成模型能算的数。本章结束时,一句话变成了一个 [T × 5120] 的矩阵(T 是 token 数,5,120 是锚点模型 Qwen3.8-27B 的宽度)。

贯穿本章的例句是「小明把苹果给了小王」(后面各章沿用),再加上对话样本里的「我喜欢机器学习」。用锚点模型的真分词器走一遍:「小明把苹果给了小王」→ 5 个 token(小明 / 把 / 苹果 / 给了 / 小王)→ 5 个 ID(115942、96373、99203、100105、126835)→ 查表得到 [5 × 5120]。同一句话用 GPT-2 的词表要 21 个 token——这一章就是在解释这中间的每一步。

累计数据流 · 从文字到下一个 token 的概率 已学本课新增还没学
解码层

点任一已学环节,看这一步的输入 → 输出形状、参数量,以及它解决了什么问题(数字取自 Qwen/Qwen3.8-27B 真实 config)。

🧭

上游: 深度学习地基 D(可选:损失、梯度下降、反向传播)与 C0 序章(模型的任务是预测下一个 token)。旧版课程这里写的「M0 算力盘点」并不存在,新结构里以地基章代替。
本章: 文字 → 切分 → Token ID → Embedding 向量。
下游: C2 位置——查表得到的向量只由 ID 决定,「小明打了小王」和「小王打了小明」得到的是同一组向量,模型分不出谁在前。

② 本章问题链

七个问题,一个接一个被逼出来

  1. 一句话怎么变成数字?——先切成词表里的块,再换成行号;码点方案在「表要 1,114,112 行」上失败。
  2. 为什么不一字一个 Token,也不一词一个 Token?——按字切,注意力打分按 T² 涨;按词切,总有没见过的词。
  3. BPE 怎么学会「该怎么切」?——反复合并最高频的相邻对;含我们项目分词器在三国演义上的真实合并日志。
  4. 词表该多大?——参数和序列长度之间的交易,用五档实测来定。
  5. Token ID 为什么不能直接拿来算?——ID 的大小只记录合并先后;Embedding 就是查表。
  6. Embedding 的数字从哪来?——随机初始化,和整个模型一起被 loss 推着走。
  7. Embedding 维度越大越好吗?——参数按 d² 涨,宽度靠实验和预算选。
  8. 实验课:同一段话交给三个真分词器,token 数差多少?

演进图:把「现代做法」按被问题推动的顺序排开。每一课都会在这张图上标出自己在哪一代。

文字 → 数字的演进:每一步都被上一步的某个真数字逼出来
  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(官方自报)。

三层交互: 概念动画(第 1 课「一句话的旅程」)→ 算法模拟器(第 3 课真 BPE 小语料训练、页面内用真合并表切新句子)→ 真模型 / 真数据(真 Qwen3.8 与 GPT-2 分词器的切分、我们项目的合并日志、五档词表扫描、训练中的 embedding 快照、三档宽度对比、实验课的实时分词)。

③ 项目推进

里程碑 M1:训练我们自己的分词器

对应 04-实践项目/MILESTONES.md 的「C1 文字 → 数字」。分工照旧:代码 AI 来写,决策你来做。分词器代码 minillm/tokenizer.py 已实现(字节级 BPE + GPT-2 预切分正则,测试 TestBPE 5 项);对照实验脚本 experiments/exp_c1_tokens.py 导出本章组件读取的 c1-tokens.json(字段约定写在 C1 设计卡末尾)。

你要拍板的决策

#决策依据(在哪一课看)
1词表多大:512 / 1,024 / 2,048 / 4,096 / 8,192 选一档第 4 课五档实测:压缩率、embedding 占比、各档模型的 val bpb(词表不同不能比 val loss)
2分词器在哪些数据上训练:只用训练集,还是训练集 + 验证集?为什么验证集不能参与第 3 课:词表由统计长出来——让验证集参与统计,等于提前「见过」考题,压缩率与 bpb 都会虚高
3输入 embedding 与输出 lm_head 共享一张表吗(tie_embeddings)第 4 课:小模型里两张表占的比例;Qwen3.8 这样的大模型不共享
4语料配比:只用三国演义(繁体古白话),还是混入简体现代文、英文第 3 课压轴与实验课:我们的分词器切简体现代句时的碎片化程度

验收标准

  • 编码 → 解码在完整验证集上逐字节还原:项目测试 test_project_tokenizer_roundtrip 通过(原理见第 1 课的往返性质)。
  • 能说出本项目的真实数字(词表 2,048 档):训练集 1,605,213 个字节(也就是合并前的 token 数)经 1,791 次合并;验证集压缩率 1.022 字/token、3.05 字节/token;合并产物里 1,059 个单字、433 个多字、299 个不完整字节;验证集里出现的 2,319 个不同汉字里 1,015 个整字是单 token;这一档训练出的模型 val bpb 为 2.194。(灰色「待实测」表示实验数据还没导出。)
  • 词表对照表:五档各自的压缩率、模型参数量、val bpb,并写出选择理由。压缩率的及格线按五档实测定——旧版课程写的「中文 ≥ 1.5 字符/token」没有实测过,在 2,048 这样的小词表上很可能达不到,不再沿用。
  • 冻结:选定的词表与合并表存进 04-实践项目/data/processed/,git 提交。之后不再改——原因见第 5 课的 Dig(embedding 按 ID 绑定)。

预告下一个坑(C7 数据章): 训练语料里如果混有大量重复的网页模板,BPE 会把整段模板学成 token,白白占掉词表名额。去重在 C7 讲。

④ 坑与带走

本章的误解与带走清单

各课就地纠正过的误解

误解真相课
Token = 一个字 / 一个词Qwen3.8 把「我喜欢机器学习」切成 2 块,「人工智能」整个是 1 块第 1 课
中文模型就是一字一 tokenQwen3.8 7 字 2 token,GPT-2 7 字 17 token第 2 课
模型看得到字母问句里的「 strawberry」是 1 个编号岔路 B1
词表是人编的字典每一项都是某一步频次合并的产物第 3 课
� 是 bug;一个汉字固定 3 个 token单个字节不是合法 UTF-8;3 个字节只是上限岔路 B2
词表拍脑袋定;vocab_size = 分词器 token 数要按规模与语料实测;Qwen3.8 分词器 248,077 项,补齐到 248,320 行第 4 课
ID 大 / ID 相近有含义ID 只记录合并先后第 5 课
每一维是一个可解释特征;token embedding = RAG 的 embedding语义分布在很多维里,且坐标轴不唯一;两者输出和训练目标都不同第 6 课
4,096、5,120 是算出来的最优值没有定理,是预算与硬件对齐下的实验选择第 7 课

工程上的坑(旧版 M1 坑表,数字已重算)

坑症状 / 后果怎么办
用英文向词表处理中文同义中文段落 GPT-2 切 461 个 token、Qwen3.8 切 106 个,训练量、API 费用、上下文窗口都按 4.3 倍消耗中文项目用中文友好的词表或自己训;先在自己的语料上测(实验课)
特殊 token 漏配模型不知道一段文字在哪结束,生成时停不下来我们的分词器已预留一个「文本结束」特殊 token;对话模板里的特殊 token 在 C12 后训练登场
训练后换分词器同一个词换了 ID,embedding 查到别的行,权重作废训练前定死、存档,和模型一起发布(第 5 课)
数不清 strawberry 的 r被当成「模型太笨」这是 token 粒度问题;需要字符级操作时让模型把词拼开写(岔路 B1)
词表大小拍脑袋d = 256 的小模型配 15 万词表,embedding 占 92.5%(旧版写「70%」,未实算)按模型规模与语料做五档扫描,比压缩率与 val bpb(第 4 课)

带走清单(各课的一句话)

  1. 分词器先按词表把文字切成块,再把每块换成它在词表里的行号;从这一刻起,模型只看得到整数。
  2. 切得越细,序列越长;切得越粗,词表越大还会遇到没见过的词——子词取中间。
  3. BPE 从单个字节出发,每一步把最常挨在一起的一对粘成新 token;切法是统计出来的。
  4. 模型数的是 token,不是字母。
  5. 字节级 BPE 永远不缺字;中文的「贵」来自词表,不来自中文本身。
  6. 词表大小是在参数和序列长度之间做交易,要用实测来定。
  7. ID 只是行号;Embedding 就是按行号查表,one-hot 乘矩阵和查表是同一件事。
  8. Embedding 表从随机数开始,和整个模型一起被预测下一个 token 的 loss 训练出来。
  9. 维度 d 让每层参数按 d² 增长,是靠实验和预算选的超参数。

概念索引: token · Token ID · 词表 · BPE · 字节级 BPE · 预切分 · UTF-8 · 压缩率 · fertility · one-hot · Embedding · hidden size · tie_word_embeddings;预告:位置编码(C2)、特殊 token 与对话模板(C12)、数据去重(C7)。

💬

有不明白的? 直接在对话里问。每个问题和解答会按课归档到 05-问答记录/,成为你自己的 FAQ 库;有价值的问题会展开成新的岔路课。

⑤ 深入这一章

想往下钻,按你愿意花的时间选

下面每一条都在 2026-09-26 实际打开核对过(页面标题、作者、时长、关键数字);本地论文可直接打开。

🎮 想更直观 10–30 分钟

用真工具玩一下,比读十页字管用
10 min界面英文 · 可输入中文需联网 开源 · 15 种以上分词器
gpt2、cl100k、o200k、Llama-3、DeepSeek-R1、Qwen2.5 等十几种分词器切同一段文字,显示切法与 ID。
对应:第 1 课(ID 只在自己的词表里有意义)、实验课(更大范围的横向比较)。理由:比页内实验覆盖的分词器多,Karpathy 视频里也用它。
5 min中文可输入需联网 OpenAI · 免登录
「你好,世界」:GPT-3(legacy)11 个 token,GPT-4 与 GPT-3.5(legacy)6 个,GPT-5.x 与 O1/3 只要 3 个(2026-09-26 实测)。
对应:岔路 B2。理由:同一家公司、同一句话,几代词表之间差近 4 倍,是「词表迭代让中文变便宜」最直接的证据。数字会随版本变,引用请带日期。
15 min英文需联网 Dartmouth PSYC 51.17 · 2026 冬季
BPE 逐步合并动画,可在「16 条简化规则」与「GPT-2 的 5,000 条真实合并」之间切换;另有 WordPiece、SentencePiece 的词表浏览。
对应:第 3 课。理由:正好接在我们的小语料模拟器与项目真实日志之后,看大词表的合并是什么样。
20 min英文需联网 官方教程 · 含思考题
用 hug / pug / pun / bun / hugs 五个带词频的词走完整轮合并,前三次合并出 ug、un、hug,中间穿插「你猜下一步合并哪一对」。
对应:第 3 课。理由:和页内的 BPE 模拟器互为印证——先亲手跑过,再看它的推导会更快。
15 min英文需联网 Google / TensorFlow
把 word2vec 的 71,291 个词 × 200 维向量用 PCA、t-SNE、UMAP 降维到 2D/3D,可搜索任意词的最近邻。
对应:第 5、6 课。理由:看一个训练好的词向量空间长什么样;同时记住 2D 投影会丢信息,远近以原始维度上的相似度为准。

🔬 想吃透原理 1–3 小时

这一档只有一个必看,其余是它的补充
2h13m中英字幕(人工精校)需联网 第三方搬运(UP 主 Web3天空之城)· 2024-02
从零手写能训练、编码、解码的 BPE 分词器,对标 GPT-4 的分词器。覆盖字符级 → 字节级的动机、正则预分块、特殊 token、SentencePiece 对比,以及 strawberry、算术、中日文更贵这些现象的根因。
对应:第 1–4 课与两条岔路。为什么是必看:唯一一个既讲清为什么、又有完整手写代码的资源。配套代码 minbpe(含 lecture.md 讲稿与 exercise.md 练习)。
长文英文需联网 fast.ai · 2025-10
把视频改写成可阅读的文章,保留全部代码。
什么时候用:不想看视频,或想快速回查某一段时。
27 min官方双语需联网 3Blue1Brown 官方账号 · 2024-04 · embedding 部分从 12:27 开始
用动画讲 embedding:词变成向量,训练好的空间里方向可以对应某种关系;以及输出端的 unembedding。
对应:第 5、6 课。理由:「向量空间里的方向」最好的可视化。看的时候记住第 6 课的纠正:方向是训练推出来的,单独某一维不一定可解释。
4–5 千字中文需联网 极客公园 · 汤一涛 · 2026-05
22 段平行文本 × 5 个分词器:Claude 系中文是英文的 1.11–1.64 倍、GPT-4o 多在 1.0–1.35 倍;Qwen 与 DeepSeek 反而中文更省(DeepSeek 低到 0.65 倍),并追到语料与合并频次的根因。
对应:岔路 B2。理由:少数把「中文税」讲出完整因果链(数据 → 算法 → 历史)的文章。
长文 + 代码英文需联网 Sebastian Raschka · 2025-01
从零实现 GPT-2 式 BPE,重点讲 256 字节初始词表的设计动机,还演示加载 GPT-2 的原版词表与合并表。
对应:第 3 课、岔路 B2。理由:代码可直接跑,和我们项目的 minillm/tokenizer.py 可以对照读。
4,500 字 + 代码中文需联网 MartinLwx · 2023-08(2024-03 更新)
从字节讲起,用一个小例子演示多轮合并,附完整可运行的训练与切分代码。
对应:第 3 课。理由:中文原创技术博客里讲 BPE 最扎实的一篇,讨论了实现细节。
2 千字英文需联网 Jian Liao · 2025-03
模型看到的是 token 而不是字母;字母被装在 token 里面,模型只能凭 token 之间的关系猜拼写。
对应:岔路 B1。理由:网上同题文章大多停在「AI 好笨」,这篇落到了 token 粒度这个根因上。
20 min中文需联网 2026-05 · 同作者另一期讲 glitch token(BV1qZRZBcEiH,24:47)
推导交叉熵对 embedding 与 lm_head 各行的梯度:输入端只有出现的 token 拿到梯度,输出端每一步都更新所有行。
对应:第 6 课。理由:把「哪些行会被改」推清楚,并连到 MiniMax「说不出马嘉祺」的真实事故。

📄 想读原文 按需

本地论文库的 PDF 点开即读
BPE 引入 NLP Sennrich, Haddow, Birch · 2015-08 · ACL 2016 · 读 §3.2
把 BPE 用于子词切分,解决翻译中的罕见词。注意归属:BPE 算法本身来自 Gage 1994,这篇的贡献是把它用来切词。对应第 2、3 课。
BPE 算法原点需联网 Philip Gage · C Users Journal · 1994-02
原始的 BPE:反复把最常见的一对字节替换成一个没用过的字节,用于数据压缩。原站已失效,这是 2022 年的存档。对应第 3 课。
字节级 BPE Radford 等 · OpenAI 2019 · 读 §2.2 Input Representation
用 256 个字节而不是 13 万以上的码点做基础词表;禁止跨字符类别合并,避免 dog. dog! 这类 token。对应第 1 课、第 3 课、岔路 B2。
可学习的词向量需联网 Bengio 等 · JMLR 2003
把每个词表示成可学习的特征向量,和语言模型一起训练——今天 embedding 表的直接前身。对应第 5、6 课。
词表大小需联网 Tao 等 · NeurIPS 2024
在 33M–3B 参数模型上扫描词表大小,拟合出最优词表随算力增大;按其拟合 Llama2-70B 应至少用 21.6 万词表(实际 3.2 万)。对应第 4 课。
宽度与形状需联网 Kaplan 等 · 2020 · 读 §1.1 与 §3.1
性能强烈依赖规模、弱依赖形状:层数与宽度之比变化 40 倍,loss 变化很小。对应第 7 课;规模定律本身在 C6 细讲。
🚫

我替你排除了什么(也是筛选标准): 「5 分钟搞懂 BPE」类速通视频(只给结论无推导)· CSDN、掘金上互相转载的同质化模板文 · strawberry 问题的猎奇新闻稿(停在「AI 好笨」)· 2023 年以前只讲 jieba 中文分词的旧文(那是词级切分,已被子词范式取代)· 把 embedding 讲成「每一维一个特征」的科普文(与第 6 课的纠正冲突)· 讲 RAG embedding 模型的教程(和本章的 token embedding 不是一回事)· GitHub 上各种个人 tokenizer 可视化小项目(不承诺维护,与 Tiktokenizer 同质)。
另注:李沐、李宏毅的频道整体质量很高,但没有专门讲分词或 BPE 的深度单集,所以本章没有列;他们的内容会在后面的章出现。