跳到主要内容

预训练 — 把「差多远」算成一个数,再把 1.24 亿个旋钮调小它

这一章讲两件事: 怎么把「模型写得好不好」变成一个可以优化的数; 以及那个数怎么驱动 1.24 亿个参数一起动——训练的完整循环。 然后书里真的点了一次火:把模型在一篇短篇小说上训 10 轮, 我们逐行读训练日志,亲眼看「学会」和「背下来」长什么样。 这是全书的中点:前面五章造出的机器,从这一章开始会干活。

1. 这一章讲什么

第 05 章结尾,组装完毕的 GPT 说了胡话("Featureiman Byeswickattribute argue")—— 因为参数全是随机数。这一章回答:从「随机」到「会续写」,中间到底发生了什么。 答案是两步:先造一把尺子(损失),再写一个循环(让尺子读数变小)。

2. 顶层全景

一把尺子(本章 §3.1):
模型的输出概率 → 挑出「正确答案那个词元」的概率 → 取对数 → 平均 → 取负
= 交叉熵损失,一个数,越小越好

一个循环(本章 §3.3):
┌─ 取一批样本 ─→ 算损失 ─→ 反向传播(算每个参数该往哪挪)─→ 挪一小步 ─┐
└──────────────── 换下一批,重复几万亿次 ←───────────────────────────┘
每隔一段:在没训过的验证集上量一次,看是真学会还是在背题

点火实录(本章 §3.4):
训练损失 9.78 → 0.39 ✓ 学会了
验证损失 9.93 → 6.45 ✗ 卡住不动——它在背原文,不是在学语言

图说:尺子、循环、点火,三件套组成全部现代 LLM 训练的骨架;
真模型的区别只在规模(数据、参数、GPU 数量)。

3. 核心原理

3.1 主走查:六步,把「差多远」算成一个数

「好不好」要变成数,机器才能优化它。这把尺子叫交叉熵(cross entropy)损失。 书里用两条真实输入走完六步1:

输入:"every effort moves" 与 "I really like"
目标(右移一位):"effort moves you" 与 "really like chocolate"

第 ①②步:过模型,取概率。 未训练的模型对两个输入各吐出三行 50,257 维的 logits, 过 softmax 变成概率。此刻它对正确答案给的分数几乎等于瞎猜: 1/50,257 ≈ 0.00002——每个目标词元只拿到约十万分之二的概率2。 真实读数:第一个样本三个目标词的概率是 [7.45×10⁻⁵, 3.11×10⁻⁵, 1.16×10⁻⁵]3

第 ③步:只取目标位置。 每个位置只关心「正确答案那个词元」的概率,其余 5 万个不看。 训练的全部目标就是把这些位置的概率顶上去4

第 ④步:取对数。 对概率取自然对数:[-9.50, -10.38, -11.37, -11.48, -9.78, -12.26]。 概率越接近 1,对数越接近 0;概率越小,对数越是大的负数5。 为什么取对数?书里坦白说「这在数学优化上更好处理,超出本书范围」,并指了附录 B 的讲义6

第 ⑤⑥步:平均、取负。 六个对数概率平均得 -10.7940;乘以 -1,得 10.7940。 这个「负的平均对数概率」就是交叉熵损失——值越小,模型给正确答案的分越高7。 PyTorch 的 cross_entropy 一步算完这六步,结果逐位相同8

这把尺子还有一个更好读的换算:困惑度(perplexity)= e 的「损失」次方。 10.7940 代进去得 48,725——读法是:模型此刻的茫然程度,等效于「每一步都在 48,725 个候选词里抓阄」。 参照物:词表一共才 50,257 个词,也就是说它几乎是纯瞎猜9。 训练有效的标志就是困惑度往下掉:从 48,725 往 10、往 5 掉。

3.2 一份数据切成两份:训练集与验证集

尺子有了,还要防止「作弊式的高分」:模型把见过的题背下来,尺子在见过的题上读数再漂亮也没用。 所以数据切成两份:训练集用来调参数,验证集训练时绝不参与调参,只用来量10

书里把《The Verdict》的 5,145 个词元按 90%/10% 切开,批大小 2、窗口 256, 得到 9 个训练批、1 个验证批。未训练模型的初始读数:训练损失 10.99、验证损失 10.98—— 两份都没见过,自然一样差11

3.3 训练循环:八步,一万次

有了尺子和数据,训练本身是一个固定动作的循环。书里给的 train_model_simple 就是这八步12:

① 轮(epoch):把整个训练集完整过一遍,叫一轮;一共训若干轮
② 批:一轮里按批取数据
③ 清零梯度:把上一批算出的「调整信号」归零(不清会累积,方向就乱了)
④ 算损失:这一批改完模型输出,用 §3.1 的尺子量
⑤ 反向传播(backpropagation):从损失出发,沿计算图倒着走,
算出每个参数对损失该负多少责——这就是每个参数的「该往哪挪、挪多少」
⑥ 优化器挪参数:按信号把每个参数挪一小步(步长 = 学习率)
⑦ 每隔几步,用验证集量一次(关掉 dropout、关掉梯度记录)
⑧ 每轮末尾,让模型续写一句话,肉眼检查

第 ⑤步是这个行业的基石,值得多说一句。反向传播就是把微积分的链式法则 (复合函数求导:外壳的导数乘内核的导数)在神经网络的计算图上从输出往输入推一遍, 一次算出全部参数各自的调整方向——1.24 亿个参数,一次反向传播全部拿到自己的那份信号13。 这就是为什么「调 1.24 亿个旋钮」在工程上可行:不是一个个试,是一次算清。

第 ⑥步由优化器(照着反向传播算出的信号、决定每个参数具体怎么挪的那个部件)执行,书里用的叫 AdamW

它在每个参数上自带一份「近期梯度走势」的记忆(最近的梯度一直在往哪边推,它记着), 让该快快的参数快、该慢慢的慢;W 是 Adam 的改良版——把「惩罚过大的权重」 (weight decay)单独拎出来做,防过拟合的效果更好,是训 LLM 的默认选择14。 「学习率」是每步挪多远的步长:太大来回震荡,太小学不动——它是人定的超参数,要试。

3.4 点火实录:学会与背下来,同时发生

现在真的点火。 配置:124M 模型、《The Verdict》5,145 词元、AdamW(lr=0.0004)、 10 轮,MacBook Air 上约 5 分钟15。训练日志的真实读数:

第 1 轮:训练 9.781 / 验证 9.933 生成:"Every effort moves you,,,,,,,,,,,,,"
第 2 轮:训练 6.661 / 验证 7.048 生成:"…you, and, and, and, and, and…"
……
第 9 轮:训练 0.541 / 验证 6.393 生成:语法通顺的英文段落
第 10 轮:训练 0.391 / 验证 6.452 生成:"…quite insensible to the irony. She wanted…"

读这条曲线有三层,一层比一层重要16:

  • 第一层:它学会了。 训练损失从 9.78 降到 0.39,从「只会接逗号」到写出语法正确的段落。
  • 第二层:它在背。 验证损失降到 6.45 就卡住不动,和训练损失拉开鸿沟; 生成的句子里 "quite insensible to the irony" 这段,拿去原文一搜,逐字在小说里。 训练损失远小于验证损失、且第二轮后两线分叉——这就是过拟合的完整长相17
  • 第三层:这是故意的。 5,145 个词元喂给一个 1.24 亿参数的模型训 10 轮,参数量是数据量的两万倍, 背下来是必然。真实预训练的做法正好相反:海量数据、只过一轮,根本不给它背的机会18

这个「失败」是全书最值钱的一课: 你亲手看到了「训练损失降」和「模型变聪明」之间的全部距离。 评估一章(原书第 5 章前半)存在的理由,就是把这层距离变成读数。

顺带把成本账补齐:这本书的教学预训练花 5 分钟笔记本电脑;真实世界里, Llama 2(70 亿参数、2 万亿词元)的账单是 18.4 万个 A100 GPU 小时、约合 69 万美元19。 同一套代码,同一套流程,差别全在规模——这正是这本书的教学法成立的原因。

4. 作者的判断与证据

有证据的: 六步损失的每个中间数、初始损失 10.99/10.98、10 轮训练日志、 验证集卡住而训练集到底的分叉、生成文本能在原文搜到——全部是书里印出的真实运行记录3111617

作者的判断:

  • 「批大小、轮数、学习率没有通解,要试」——书里在多处明说这些是超参数,要靠观察损失曲线来调20
  • 用一篇短篇小说教学是刻意的:5 分钟跑完 vs 几周,教学目的足够21
  • AdamW 优于 Adam 的理由(单独做 weight decay)是文献结论,作者直接采用14

判断(我们的,不是书里的): 很多材料把「过拟合」讲成一条定义,这本书把它讲成一段录像: 你能看到逗号复读阶段、"and"复读阶段、语法通顺阶段、背原文阶段——四个阶段在同一次训练里依次出现。 读完这一章,「训练损失降、验证损失平」这八个字在你脑子里应该永远带着这段录像。 如果错,会错在: 如果读者据此以为「过拟合 = 训练失败」——不对。在小模型+小数据上它是教学演示; 在大模型+大数据上,一定程度的记忆甚至与泛化能力纠缠在一起,今天的研究还没把它完全分开。

5. 边界与局限

  • 这个训练循环是「能讲清楚」的最小版:没有学习率预热(训练开头几步把步长从小慢慢爬到峰值,不一脚油门踩到底)、没有余弦衰减、没有梯度裁剪。 这三件真实训练里的标配在附录 D,我们放在第 10 章讲。
  • 困惑度只能跟「同一词表」的模型比;换分词器,数就不可比——书里没强调,值得记住。
  • 「反向传播一次算清全部参数」的工程细节(计算图怎么存、梯度怎么累)在附录 A, 同样归到第 10 章。
  • 验证书只用 5 个批估一次(eval_iter=5),是省时间的近似;小数据上够了,大项目要放全量。

6. 可带走的

  1. 交叉熵损失六步:概率 → 取目标位置 → 对数 → 平均 → 取负;它把「写得好不好」变成一个可优化的数。
  2. 困惑度 = e^损失,读作「等效于在多少个词里抓阄」;未训练的 GPT-2 词表模型约等于 48,725(≈词表大小)。
  3. 训练集调参数,验证集只量不调;两线分叉 = 过拟合的现场。
  4. 训练循环八步是固定动作;第 ③ 步「清零梯度」忘了,方向会乱(梯度累积:上一批的调整信号残留下来、叠进这一批)。
  5. 反向传播 = 链式法则在计算图上从右往左推,一次算清所有参数的调整方向——这是「能训 1.24 亿个旋钮」的原因。
  6. AdamW = 带记忆的步长 + 单独做的权重惩罚;学习率没有通解,要试。
  7. 过拟合不是抽象概念:训练 0.39 vs 验证 6.45,生成句在原文里逐字搜得到,这就是它。
  8. 真实预训练用海量数据只过一轮;教学演示用一篇小说过十轮——同一个循环,两个极端。
  9. 成本量感:教学版 5 分钟笔记本;Llama 2 7B 约 69 万美元。规模差六个数量级,代码同一套。

7. 原文地图

主题原书章原文位置
未训练模型约等于瞎猜5 Pretraining on unlabeled datatext/13-ch05-5-pretraining-on-unlabeled-data.txt:351(搜「0.00002」)
六步算损失同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:400(搜「7.4541e-05」) · text/13-ch05-5-pretraining-on-unlabeled-data.txt:452(搜「-9.5042」) · text/13-ch05-5-pretraining-on-unlabeled-data.txt:529(搜「10.7940」)
困惑度同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:531(搜「Perplexity」)
训练/验证切分与初始损失同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:686(搜「train_ratio」) · text/13-ch05-5-pretraining-on-unlabeled-data.txt:812(搜「10.98758347829183」)
八步训练循环同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:849(搜「pass over a training set」) · text/13-ch05-5-pretraining-on-unlabeled-data.txt:897(搜「train_model_simple」)
AdamW同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:984(搜「AdamW」)
10 轮点火实录与过拟合同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:1014(搜「9.781」) · text/13-ch05-5-pretraining-on-unlabeled-data.txt:1024(搜「quite insensible to the irony」)
真实预训练只训一轮同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:1081(搜「only one epoch」)
Llama 2 成本账同上text/13-ch05-5-pretraining-on-unlabeled-data.txt:595(搜「184,320 GPU hours」)

Footnotes

  1. 出处:「5 Pretraining on unlabeled data」第 251 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:251,搜「16833, 3626, 6100」)。

  2. 出处:「5 Pretraining on unlabeled data」第 351 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:351,搜「0.00002」)。 原文:「most of the initial probabilities will hover around 0.00002 (1/50,257)」。

  3. 出处:「5 Pretraining on unlabeled data」第 400 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:400,搜「7.4541e-05」)。 2

  4. 出处:「5 Pretraining on unlabeled data」第 403 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:403,搜「maximize the likelihood of the correct token」)。

  5. 出处:「5 Pretraining on unlabeled data」第 452 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:452,搜「-9.5042」)。

  6. 出处:「5 Pretraining on unlabeled data」第 455 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:455,搜「detailed it further in a lecture」)。

  7. 出处:「5 Pretraining on unlabeled data」第 464 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:464,搜「-10.7940」)与第 477 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:477,搜「cross entropy loss」)。

  8. 出处:「5 Pretraining on unlabeled data」第 524 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:524,搜「cross_entropy」)。

  9. 出处:「5 Pretraining on unlabeled data」第 541 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:541,搜「48725」)。 原文:「the model being unsure about which among 48,725 tokens in the vocabulary to generate as the next token」。

  10. 出处:「5 Pretraining on unlabeled data」第 622 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:622,搜「divide the dataset into a training and a validation set」)。

  11. 出处:「5 Pretraining on unlabeled data」第 744 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:744,搜「nine training set batches」)与第 812 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:812,搜「10.98758347829183」)。 2

  12. 出处:「5 Pretraining on unlabeled data」第 849 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:849,搜「pass over a training set」)与第 897 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:897,搜「train_model_simple」)。

  13. 出处:「5 Pretraining on unlabeled data」第 407 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:407,搜「Backpropagation」)与附录 A 第 503 段(text/16-apx-a-appendix-a-introduction-to-pytorch.txt:503,搜「chain rule」)。 附录 A 原文:「backpropagation…can be considered an implementation of the chain rule from calculus for neural networks」。

  14. 出处:「5 Pretraining on unlabeled data」第 984 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:984,搜「AdamW」)。 原文:「AdamW is a variant of Adam that improves the weight decay approach」。 2

  15. 出处:「5 Pretraining on unlabeled data」第 1001 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:1001,搜「lr=0.0004」)与第 1011 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:1011,搜「5 minutes」)。

  16. 出处:「5 Pretraining on unlabeled data」第 1014 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:1014,搜「9.781」)与第 1023 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:1023,搜「0.541」)。 2

  17. 出处:「5 Pretraining on unlabeled data」第 1024 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:1024,搜「quite insensible to the irony」)。 原文:「This divergence…indicate that the model is overfitting to the training data. We can confirm that the model memorizes the training data verbatim by searching for the generated text snippets」。 2

  18. 出处:「5 Pretraining on unlabeled data」第 1081 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:1081,搜「only one epoch」)。

  19. 出处:「5 Pretraining on unlabeled data」第 595 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:595,搜「184,320 GPU hours」)。

  20. 出处:「6 Fine-tuning for classification」第 1426 段(text/14-ch06-6-fine-tuning-for-classification.txt:1426,搜「an epoch number of five is usually a」)。 原书第 6 章的选轮数框:「there is no universal solution or recommendation, although an epoch number of five is usually a good starting point」。

  21. 出处:「5 Pretraining on unlabeled data」第 619 段(text/13-ch05-5-pretraining-on-unlabeled-data.txt:619,搜「5,145 tokens」)。