跳至内容
11/30第 11 章,共 30 章

从基础模型到助手:SFT、RLHF、DPO 与 GRPO

向基础模型要一首俳句,它会把同一句话写五遍。再看 reward model 如何学会偏爱长度而不是正确性。

本页内容

让 GPT-2——一个预训练得相当不错的语言模型——写一首关于大海的俳句:

TEXT
prompt: Write a haiku about the sea.

The sea is a beautiful place.

The sea is a beautiful place.

The sea is a beautiful place.

The sea is a beautiful place.

The sea is a beautiful place.

它并没有困惑,也没有把自己的工作搞砸。它正在做 第 10 章 训练它做的事:给定一些文本,生成看起来合理的后续文本。在互联网上,像 Write a haiku about the sea. 这样的一行,后面经常跟着关于大海的散文;而一个刚刚出现过的句子,也异常容易再次出现。这个模型是出色的 next-token 预测器,却是毫无用处的助手。

现在,把同样的请求交给一个以同样方式构建的模型——Qwen2.5,5 亿参数,是上面 GPT-2 的四倍大小,但按 2026 年的任何标准看仍然很小——只不过它经过了本章要讲的这些训练阶段:

TEXT
Whispers of the ocean,
Silent depths where waves meet,
Mysteries in the vast blue.

四倍参数并不会教会模型停止说话。两个输出之间的差距,不是规模,不是架构,也不是数据量。它是 post-training:一个比预训练小几个数量级的第二阶段,把文本预测器变成会回答的东西。

第一阶段:让它看见答案应该是什么样

链接到此部分:第一阶段:让它看见答案应该是什么样

第一步最不光鲜,却完成了大部分工作。收集指令与优质回答配对的样例,然后继续用 第 8 章 里的同一个损失训练它——预测下一个 token——但只在回答部分计算。这就是 supervised fine-tuning,或 SFT。

这里并没有教给模型任何新的语言知识。被教会的是一种 格式:这种形状的文本后面,应该接那种形状的文本,然后它会停下。再看基础模型的失败。它在第一句话里已经回答了问题,然后却停不下来,因为它的训练中从未标记过一个回答的结束。停止是一种习得的行为。

这也是为什么必须告诉模型边界在哪里,而这正是 chat template 的作用:

TEXT
<|im_start|>system
You are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>
<|im_start|>user
What is the capital of France?<|im_end|>
<|im_start|>assistant

那些 <|im_start|><|im_end|> 标记是真实存在于词表中的 token,在 fine-tuning 之前加入;模型在这些精确位置上看过数百万次。它就是靠它们知道轮到谁说话,以及一轮对话在哪里结束。

跳过 template,直接把一个裸问题交给模型,你给它的就是一段它在训练中没见过的序列。实测,同一个模型、同一个问题、同样的 greedy decoding:

不使用 template——原始字符串 What is the capital of France?

TEXT
 The capital of France is Paris.

To verify this, I will use a simple
Python code snippet to confirm that
Paris is indeed the capital city of
France.

[...and then it starts writing a
Python script to check its own answer]

使用 template

TEXT
The capital of France is Paris.

两个答案都对,但没有标记时,模型会漂移到写 Python 来自检,因为它收到的 prompt 和它 fine-tuning 时见过的东西完全不像。这就是「我直接调用模型后,它变笨了」最常见的原因:template 不是模型外面的装饰,它是模型的一部分;错误的 template 会悄无声息地降级,而且不会附带任何报错。

SFT 有天花板,而天花板就是数据。要在示范答案上做 fine-tuning,你需要有人写出理想回答——而对大多数有意思的问题来说,写出好答案很难、很慢、很贵,并且只产生一个你无法验证质量的答案。

人类擅长的是比较。给标注员看两个回答,他通常能在几秒内可靠地说出哪个更好,即使他自己写不出其中任何一个。整个第二阶段都建立在这个事实之上,而这也是多数解释说反了的地方:

人类不写答案。他们给成对答案排序。

所以数据是成对的——一个 prompt、两个回答,以及哪个赢了。这不能直接塞进 next-token loss,因为没有目标序列。它需要另一台机器。

Reward model,以及它实际学到了什么

链接到此部分:Reward model,以及它实际学到了什么

你不能在训练期间让人类给每个回答打分——那会是数百万次判断。所以你训练一个模型来模仿人类:一个 reward model,它接收一个回答并返回一个标量。

用比较数据训练它,会用到一个 1952 年的结果。Bradley–Terry 模型2 说,如果两个对象有潜在强度,一个打败另一个的概率就是它们差值的 logistic function。把这个反过来,它就变成一个损失:已知人类更偏好 ywy_w 而不是 yly_l,最大化

P(ywyl)=σ(r(yw)r(yl))P(y_w \succ y_l) = \sigma\big(r(y_w) - r(y_l)\big)

用代码写出来,就是整个训练循环:

reward_model.pyPYTHON
loss = -F.logsigmoid(reward(chosen) - reward(rejected)).mean()   

注意模型从未见过什么:绝对分数。它学到的永远只有差异,而这正是数据所包含的东西。

现在来看值得测量的部分。reward model 学到的是标注员奖励的东西,而标注员是人。下面是一个模拟:回答的 真实 质量只取决于有用和正确——长度没有任何价值——但模拟标注员在其他条件接近时,会对更长的回答有轻微偏好,而这是一种有充分文献记录的人类偏差。在 2000 次比较上训练 reward model,然后读取它的权重:

标注员的长度偏差学到的 有用 权重正确 权重长度权重
0.0+1.00+1.00+0.01
0.3+0.98+1.00+0.15
0.6+0.97+1.00+0.27
1.2+1.00+0.99+0.59

reward model 工作得非常完美。它忠实学会了展示给它的偏好——包括这些偏好中与质量毫无关系的部分。reward model 不是对「好」的度量;它是对标注员选择内容的度量,而标注池里的每一种偏差,现在都成了一个可微函数里的系数,接下来一个大得多的模型就要对着它优化。

这就带我们来到优化它时会发生的事。给 policy 一份固定的努力预算,让它在回答的各项属性之间分配,并加入一个现实的不对称:有用和正确都很昂贵,而变长很便宜——继续写就行。

对上面训练出的模型来说,每单位努力带来的 reward:有用 8.26,正确 8.31,长度 31.70。长度的收益几乎是正确性的四倍,不是因为 reward model 坏了,而是因为它便宜。

对这个 reward 做优化,然后同时观察两个数字:

reward model 的分数真实质量生成长度
起始 policy12.5880.9743.365
优化后31.6960.00012.497

reward 提高了 2.5 倍。reward 本该衡量的东西降到了 。policy 发现,只要写得很长并且什么也不说,就能拿到极高分;训练循环的任何部分都没有办法发现这一点,因为在循环内部,reward model 就是 对「好」的定义。

这就是 reward hacking。如果你曾经好奇为什么聊天模型这么啰嗦,这张表就是很大一部分答案。

标准防御办法是惩罚 policy,让它不要偏离起点太远,用 第 4 章 的 KL divergence 来度量距离:

objective=E[r(y)]βDKL(πθπref)\text{objective} = \mathbb{E}\big[r(y)\big] - \beta \, D_{\mathrm{KL}}\big(\pi_\theta \,\|\, \pi_{\text{ref}}\big)

参考 πref\pi_{\text{ref}} 是 SFT 模型——强化阶段之前的 policy。这个说法是,它能防止模型漂移到退化行为里。让我们看看这个说法在测量后还能剩下多少。同样的设置,扫描 β\beta

β\betareward真实质量长度KL
031.6990.00012.4982.994
131.6970.00012.4972.993
528.3180.28510.7002.163
1512.8601.5422.5520.151
3010.4261.7191.3030.025
609.6321.7690.9080.005
仅 reference model9.1621.7910.6870

把最后一行和其余行一起读。在 β=0\beta = 0β=1\beta = 1 时,惩罚完全不起作用:reward 比 KL 值钱太多,优化器交罚款也照样 hack。5 到 15 之间,行为发生摆动。而到了 β=60\beta = 60,真实质量回升到 1.769——但这仍然低于 reference model 在这一切开始前已有的 1.791

在任何人引用这个数字之前,先加一个注意事项:最后一行的 1.791,以及第一张表给 starting policy 的 0.974,是对同一个 pre-RL 模型的两次不同测量,分别来自两个实验。只能在同一张表内比较行,不要跨表比较——每张表的结论都由自身行支持,并且都不依赖另一张表的 baseline。

所以诚实的总结不是「KL 惩罚防止 reward hacking」。而是:

KL 惩罚不能防止 reward hacking。它限制 policy 能从 reference 移动多远——而既然失败需要移动,这确实有帮助。但它是一根绳索,不是纠偏器:在低 β\beta 时,绳索会断;在高 β\beta 时,你拿回的是 reference model,整个昂贵阶段什么也没买到。

有用区间很窄,它的位置取决于 reward model,而且除了观察之外没有办法找到它。这就是为什么 reference model 必须足够好——KL 是 reference 质量的地板,而不是失败的天花板——也是为什么这个阶段在实践上很难,而不是在原则上很难。

让这件事能在规模上工作的算法是 Proximal Policy Optimization3 用一段话概括:它估计每个回答的 advantage,更新 policy 以提高高于 baseline 的回答概率,并裁剪任意单次更新的大小,防止一个很大的 advantage 估计一步摧毁 policy。应用到语言模型4 时,这意味着同时保留四个模型——policy、reference、reward model 和 critic——并且在整个训练过程中让 policy 持续生成新样本。

它有效,它产出了 InstructGPT 和所有从它衍生的东西,而且它确实很难:四个模型在内存中、训练循环里采样,以及当之无愧的不稳定名声。假装你能在一篇博客里实现它是不诚实的,所以本章不这么做。

在大多数用途上取代它的东西,来自一个观察。上面的 KL-regularized objective 有一个 closed-form 最优 policy,而这个表达式可以反过来:reward 可以用最优 policy 和 reference 来写。把它代回 Bradley–Terry loss,reward model 就完全消失了。剩下的是 preference pairs 上的 supervised loss——不采样,没有 critic,没有 reward model,内存里两个模型而不是四个。

这就是 Direct Preference Optimization5 两行代码:

dpo.pyPYTHON
def dpo_loss(pi_w, pi_l, ref_w, ref_l, beta=0.1):
    """pi_* and ref_* are summed log-probabilities of a full response."""
    logits = beta * ((pi_w - ref_w) - (pi_l - ref_l))   
    return -F.logsigmoid(logits)                        

读一读它在说什么。被推高的量是:policy 相比 reference 对赢家的偏好增加了多少,减去它相比 reference 对输家的偏好增加了多少。reference 不是之后螺栓式加上的惩罚——它就在 loss 里面,这就是为什么 DPO 不需要单独的 KL 项。

最重要的性质在 gradient 里。对同一对样本,在 policy 的五种不同状态下计算 loss 和 gradient:

policy 的状态lossgradient magnitude
已经强烈偏好赢家0.51300.0401
已经偏好赢家,但很弱0.66850.0488
与 reference 相同0.69310.0500
偏好输家0.79810.0550
强烈偏好输家1.00550.0634

当 policy 错得越厉害,gradient 就越大。模型已经处理好的样本几乎不贡献什么;它搞反的样本主导更新。DPO 会根据 policy 当前错得有多离谱,自动给每个样本加权,不需要任何调度——而这种自加权机制,正在完成 PPO 的 advantage 估计和 critic 曾经完成的工作。(第三行的 loss 正好是 ln2\ln 2,这是检查任何实现的锚点:与 reference 完全相同的 policy 什么也没学到,应该停在 ln2\ln 2。)

GRPO6 走的是解决同一问题的另一条路。它保留采样循环,但删除 critic:它不训练一个模型来预测 baseline,而是对同一个 prompt 采样一 回答,并直接使用这组的平均 reward 作为 baseline。一个回答的 advantage,就是它比自己的兄弟回答好多少。这样用更大的 batch 换掉了整个模型,也正是它让可验证 reward 训练——第 12 章 的主题——变得可行。

查看详情

post-training 版图上的另外三块,简要说。

RLAIF 和 Constitutional AI。7 标注员不一定必须是人。给模型一套写下来的原则,让它批评并修改自己的输出,或者在两个候选之间做选择,你就得到了一份以机器速度和成本生成的偏好数据集。显而易见的反对意见——模型在给自己的作业打分——是真实的;诚实的回答是,它比听起来更有效,因为判断比生成更容易,而这正是整章建立其上的同一个不对称性。

LIMA,以及这到底需要多少数据。8 一千条精心筛选的示范就产出了一个有竞争力的助手。提出的解释是:预训练已经安装了知识和格式,post-training 只需要选择模型现有行为中的哪些浮现出来。如果这是真的,post-training 数据的质量就压倒数量——而此后整个领域的行为表明,人们相信这一点。

LoRA 和 QLoRA。910 对大模型的每个权重做 fine-tuning,需要为权重、它们的 gradient 和优化器状态准备内存——也就是第 10 章的每参数 16 字节,覆盖 第 6 章 手工构建的两个平均量——规模大到需要集群。LoRA 冻结原始权重,并在旁边训练一对低秩矩阵,把可训练参数减少几个数量级;QLoRA 还会把冻结的 base 量化到 4 bit。二者在这里作为 technique 覆盖。fine-tuning 到底是不是值得花钱做的事,是另一个问题,那是 第 20 章 的问题。

有两件事要带到后面。

第一,这个阶段有成本,而它表现为能力。模型在 alignment training 之后,往往会在一些基准任务上出现可测量的变差——也就是 alignment tax——因为目标变了:一个安全、留有余地且格式良好的回答,并不总是最大化准确率的回答。其中一部分差距已经被工程手段消除了,另一部分则是真实取舍,而不是待修复的 bug。

第二,是 aligned 这个词藏起来的问题。与谁对齐?链条是:一家公司写下准则,外包人员解释它们,他们的比较训练出 reward model,reward model 塑造 policy,而 policy 回答一个从未见过这一切的人提出的问题。每一环都是由具体的人做出的选择,而本章没有任何算法会对这些选择是否正确发表意见。

这不是修辞。它是两个 frontier model 会拒绝不同请求、同一个模型会在不同版本之间改变主意,以及为什么「aligned」描述的是一个 过程 而不是一个 artefact 属性的具体原因。本章中的数学已经定了。那部分没有。

Post-training 教会了模型回答。它没有教会模型在回答前 思考,而二者的差别后来证明也是可训练的。

第 12 章讲的是:当你让模型在回答时,而不是训练时,为一个难题花更多计算,会发生什么——chain of thought、来自可验证 reward 的强化学习,以及为什么一个展示推理过程的模型不仅是在解释自己,而是在以不同方式计算。它还会偿还本章欠下的债:GRPO 会出现在那里,承担 PPO 的 critic 过去承担的工作,并且使用完全不需要标注员的 reward,因为一个证明要么能通过检查,要么不能。


上面的生成来自 gpt2Qwen/Qwen2.5-0.5B-Instruct,并使用 greedy decoding,因此可以精确复现。如果你想运行真实流程而不是模拟,Hugging Face LLM Course 的第 11 章会用 trlpeft 讲解 SFT 和 DPO;Sebastian Raschka 的 Build a Large Language Model (From Scratch) 第 7 章则在不依赖库的情况下端到端实现 instruction fine-tuning。

  1. Sutton, R. S. and Barto, A. G. Reinforcement Learning: An Introduction, 2nd edition (MIT Press, 2018)。这里的委托是有意的:上面的词汇框是最小可用子集,而真正的主题是一本书。

  2. Bradley, R. A. and Terry, M. E. Rank Analysis of Incomplete Block Designs: I. The Method of Paired Comparisons. Biometrika 39(3/4), pp. 324–345 (1952)。今天所有在用的 reward model 背后的成对比较模型。

  3. Schulman, J., Wolski, F., Dhariwal, P., Radford, A. and Klimov, O. Proximal Policy Optimization Algorithms. arXiv:1707.06347 (2017)。

  4. Ouyang, L. et al. Training language models to follow instructions with human feedback. arXiv:2203.02155 (2022)。InstructGPT——让三阶段配方成为标准的论文。此前还有 Christiano et al.(arXiv:1706.03741),它引入了从人类比较中学习 reward model;以及 Stiennon et al.(arXiv:2009.01325),它将其应用到摘要任务。

  5. Rafailov, R., Sharma, A., Mitchell, E., Ermon, S., Manning, C. D. and Finn, C. Direct Preference Optimization: Your Language Model is Secretly a Reward Model. arXiv:2305.18290 (2023)。移除 reward model 的推导在第 4 节,值得完整阅读;它比名声听起来短。

  6. Shao, Z. et al. DeepSeekMath: Pushing the Limits of Mathematical Reasoning in Open Language Models. arXiv:2402.03300 (2024)。在第 4.1 节引入 GRPO。

  7. Bai, Y. et al. Constitutional AI: Harmlessness from AI Feedback. arXiv:2212.08073 (2022)。

  8. Zhou, C. et al. LIMA: Less Is More for Alignment. arXiv:2305.11206 (2023)。

  9. Hu, E. J. et al. LoRA: Low-Rank Adaptation of Large Language Models. arXiv:2106.09685 (2021)。

  10. Dettmers, T., Pagnoni, A., Holtzman, A. and Zettlemoyer, L. QLoRA: Efficient Finetuning of Quantized LLMs. arXiv:2305.14314 (2023)。

准备好让 LIA 替你选模型了吗?

所有 AI 模型都在一处——今天就免费开始。