一个大模型要过三段训练:预训练学语言,指令微调学听话,偏好学习学分寸。 三段的目标函数不一样,数据形态不一样,成本差着几个数量级。 这一节把三段的损失各算一遍,并且说清楚:本书第 3、5 章做的微调,停在哪一段。
41 课 图解深度学习 里有反向传播的推导, 43 课 深度学习入门教室 里有训练循环的写法。 这一节不推公式,只讲三段训练各自「在什么数据上、算哪个位置的损失」。
一、第一段:无监督预训练
目标只有一句话:看着前面的词,猜下一个词。猜错了算交叉熵,反向传播改参数。 它为什么叫「无监督」?因为标签是现成的——下一个词本身就是答案,不需要人来标。 一整本书、一整个网页,每一处都是训练样本。 这就是它能吃下 2 万亿 token 的原因。换成人工标注,同样规模的语料要几百年。
代价在算力。Llama 2 的预训练用了 2 万亿 token,几千张 A100 跑几个月。 这一段的成本,比后面两段加起来还高两个数量级。 这一段的产出叫基座模型。 它会续写,但不会听话——你问它「帮我总结这段」,它可能接着给你编一段「帮我总结这段」的后文, 因为在它的世界里,网页上出现这句话之后,跟的往往还是类似的话。
二、第二段:指令微调
第二段喂的是「提问加回答」的成对数据,让人写标准答案,模型照着学。这叫监督微调,简称 SFT。 关键的一个技术细节是损失屏蔽:提问那一段不算损失,只算回答那一段。 因为提问是用户写的,模型不需要学会生成提问,它只需要学会「接着提问往下答」。 为什么要屏蔽,可以从梯度看:不屏蔽的话,提问段也会回传梯度,模型会被推着去学「怎么提问」。 这在数据量大的时候影响不大,在数据量小的时候会把模型带偏成「自问自答」。
这一段的数据量比预训练小四五个数量级。Llama 2 用了十万条量级的人工标注对话。 2023 年有一篇叫 LIMA 的工作更极端:只用一千条精选数据,效果就相当能打。 这说明这一段拼的不是量,是质。 还有一处容易忽略:多轮对话要拼成一条完整序列,前面的轮次也要进上下文,但只有助手说的话算损失。 第 4 章会专门处理这件事。
三、第三段:基于人类反馈的微调
第二段之后模型会答了,但答得未必合人心意——太啰嗦、太保守、该拒绝的不拒绝。 第三段解决的是「哪个答法更好」,而不是「标准答案是什么」。 做法分两步。先让人对同一个问题的多个回答排序,用这些排序训一个奖励模型,让它学会给回答打分。 再用强化学习(PPO)让模型去最大化这个分数。 直接最大化会出问题:模型会找到奖励模型的漏洞,输出一堆「看起来高分」的废话。 所以加一个 KL 惩罚,约束新模型不要离第二段的结果太远。
2023 年有个更简单的做法叫 DPO:不算奖励模型,直接把「好答案比差答案概率高多少」写成一个损失, 一步优化到位。省掉一整个模型和一轮采样,工程上友好得多。 这一段的成本介于两者之间:数据量比 SFT 还小,但要人做排序,标注更贵; 算力比预训练省得多,但要跑采样,比 SFT 慢。
四、三段之外,还有第四件事
实际工业流程里,三段之后还要做对齐与安全:红队测试、拒答训练、上下文蒸馏。 这些不在本书范围内,但要知道它们存在——开源模型和能上线的模型,差别常常在这一步。 把三段摆在一起,普通开发者能碰的只有第二段。第一段要几千张卡,第三段要人做排序。 所以这本书第 3 章、第 5 章讲的「微调」,全部是第二段,外加以 LoRA 为代表的省显存做法。
五、动手 Demo:三段训练,三种损失,各算一遍
这一节不训模型,只把三段的损失函数各写一遍、各算一遍,看它们的数长什么样。 预训练段用十二个词的序列算逐位交叉熵; 指令微调段对比「整段都算」与「只算答案段」两种算法的参与位置数与平均损失; 偏好学习段用一组构造好的对数概率算 DPO 损失。
# 第一段:每个位置都算交叉熵
for i in range(len(seq) - 1):
ce = -math.log(softmax(logits[i])[seq[i + 1]])
# 第二段:提问段遮掉,只算答案段
loss_all = mean([ce(i) for i in range(len(ids) - 1)])
loss_ans = mean([ce(i) for i in range(len(prompt), len(ids) - 1)])
# 第三段:DPO,好答案与差答案相对参考模型的优势差
margin = (lp_w - ref_w) - (lp_l - ref_l)
loss = -math.log(1.0 / (1.0 + math.exp(-beta * margin)))
实跑输出:
--------------------------------------------------------------------
三段训练:预训练、指令微调、偏好学习,损失各算一遍
--------------------------------------------------------------------
① 预训练:整段都算损失
--------------------------------------------------------------------
| 看到 | 该预测 | 交叉熵 |
|---|---|---:|
| 客 | 户 | 2.66 |
| 户 | 要 | 2.96 |
| 要 | 求 | 2.64 |
| 求 | 改 | 2.74 |
| 改 | 图 | 2.80 |
| 图 | 纸 | 2.16 |
11 个位置全算,平均交叉熵 2.633 纳特,困惑度 13.92。
! 预训练的数据不需要人标,因为「下一个字」本身就是标签——这就是「无监督」这三个字的实际含义。
② 指令微调:只算答案那一段
--------------------------------------------------------------------
| 算法 | 参与的位置数 | 平均损失 |
|---|---:|---:|
| 整段都算 | 9 | 3.556 |
| 只算答案段 | 4 | 3.447 |
同一批数据,只算答案段时参与的位置从 9 个降到 4 个。
这里两组损失差得不多(3.556 对 3.447),因为权重是随机抽的,本来就没学会什么。
真正的作用不在损失值,在于梯度从哪些位置回传:遮掉提问段,模型就不会被推着去学「怎么提问」。
! 为什么要把提问那段遮掉:提问是用户写的,模型不需要学会「生成提问」,
它只需要学会「接着提问答」。遮掉就是告诉它这一段不记账。
③ 偏好学习:比较两个回答
--------------------------------------------------------------------
| 量 | 当前模型 | 参考模型 |
|---|---:|---:|
| 好答案的对数概率 | -2.10 | -2.30 |
| 差答案的对数概率 | -3.40 | -3.10 |
相对参考模型的优势差 = 0.500,乘上 beta=0.1 后取 -log sigmoid,损失 0.6685。
这个损失只关心「好答案比差答案高多少」,不关心好答案的绝对概率。
! 所以 RLHF 教的是「哪个答法更好」,不是「标准答案是什么」——前者是排序,后者是抄写。
这就是它跟指令微调最根本的区别。
④ 三段的数据与代价
--------------------------------------------------------------------
| 阶段 | 数据 | 标注成本 | 算力 |
|---|---|---|---|
| 预训练 | 几万亿 token 的网页与书 | 不需要人标 | 几千张卡跑几个月 |
| 指令微调 | 几万到几百万条问答对 | 要人写答案 | 几张卡跑几小时到几天 |
| 偏好学习 | 几万条「这两个哪个好」 | 要人打分排序 | 比微调更轻,但要先训奖励模型 |
三段里最贵的是第一段,最便宜的是第三段,但第三段最依赖人。
! 本书第 3、5 章要做的微调,都停在第二段——普通人手上没有能跑第一段的机器,也不需要跑第三段。
第一段那张表,每行是「看到某个字、该预测下一个字、扣多少分」。 十一个位置全算,平均交叉熵 2.633 纳特,换成困惑度是 13.92。 词表是十二个词,所以「完全瞎猜」的基准是 12,13.92 说明这个随机初始化的模型还没学到东西。 这一段最该记住的是那句话: 预训练的数据不需要人标,因为「下一个字」本身就是标签。「无监督」这三个字说的不是「没人管」, 是「不用人写答案」。 第二段的两组数字差得不多(3.556 对 3.447),因为权重是随机抽的,本来就没学会什么。 但参与的位置数从 9 个降到 4 个,这个差别是实打实的:梯度只从答案段回传。 为什么要遮提问,从梯度看最清楚。不遮的话,模型会被推着去学「用户会怎么问」; 遮掉之后,它只学「接着这个问题该怎么答」。数据量越小,这个区别越明显。 第三段算出来 0.6685。 这个数本身没有意义,有意义的是它的结构:它只看「好答案比差答案高多少」,相对参考模型算, 所以不关心好答案的绝对概率。这就是 RLHF 与 SFT 最根本的区别——一个学排序,一个学抄写。 最后那张成本表要竖着看:预训练几千张卡跑几个月,指令微调几张卡跑几小时, 偏好学习算力更省但要人做排序。三段里最贵的第一段,恰好是本书碰不到的那一段。
30 秒实验
- 把第二段的
prompt长度从 5 改成 2,看「只算答案段」的参与位置数与平均损失怎么变。 想一想:如果提问占了整条序列的九成,遮掉之后还剩多少训练信号? - 把第三段的
beta从 0.1 改成 1.0,损失会变成多少? 再想想 beta 调大意味着「更贴近参考模型」还是「更敢偏离」。 - 把第一段的词表从 12 扩到 120,重新随机初始化,看平均交叉熵跑到多少。
它跟
log(120)是什么关系?
常见误区
- 以为「无监督预训练」是不需要人参与。 它不需要人标答案,但需要人决定喂什么、洗成什么样——第 1.3 节整节都在讲人在哪里使劲。
- 以为 SFT 数据越多越好。 一千条精选能顶十万条凑数,因为这一段学的是「格式与口吻」,不是「知识」。 知识在预训练那一段就进去了。
- 以为 RLHF 是「让模型更聪明」。 它不让模型变聪明,它让模型的输出更符合人的偏好——偏好和正确是两件事,一个讨喜但答错的模型, 在偏好分数上可能很高。
自测三问(点开对答案)
1. 为什么指令微调要把提问那一段的损失遮掉? —— 因为提问是用户给的,不是模型该生成的东西。 遮掉之后梯度只从答案段回传,模型学的是「接着问往下答」。 不遮的话,模型会被推着去学「用户会怎么问」,数据量小时会退化成自问自答。 2. KL 惩罚在 RLHF 里管什么? —— 管「别跑太远」。只最大化奖励,模型会去找奖励模型的漏洞,输出看着高分实际没用的东西。 KL 惩罚把新模型拽在 SFT 结果附近,让它在「讨喜」和「还算正常」之间取平衡。 3. 这本书为什么只做第二段的微调? —— 第一段要几千张卡跑几个月,个人和小团队没有;第三段要人做大量排序标注,成本比算力还高。 第二段配 LoRA 之后,一张消费级显卡就能跑, 而且效果对绝大多数「让它按我的格式说话」的需求已经够了。下一节讲怎么判断训出来的模型到底行不行——评测这件事,比想象中难。
- ☐ (本篇完,下一篇 1.5 大模型的评测)
相关笔记
- 43 课 深度学习入门教室:训练循环与损失函数
- 39 课 AI训练师手册 2:偏好标注那一侧的做法
- 🦙 Llama 大模型实践 · 索引