Skip to main content

第17章:对齐训练

上一章我们完成了 SFT(Supervised Fine-Tuning,监督微调),模型已经学会了"按指令回答"的基本格式。但很快你会发现一个令人不安的问题:SFT 之后的模型仍然可能输出有害内容、捏造事实、或者说违心的话

原因在于 SFT 只教会了模型模仿训练集的风格和格式,却没有教它什么是好的回答。模型并不真正理解"诚实"或"无害"的含义——它只是在拟合文本分布。

这就引出了本章的核心问题:如何让模型的输出真正符合人类的价值观和偏好?


17.1 RLHF 原理与 PPO 实现

基本思路:用人类反馈作为信号

RLHF(Reinforcement Learning from Human Feedback,基于人类反馈的强化学习)的核心思路很朴素:

  1. 让模型对同一个问题生成多个候选答案
  2. 让人类标注员对这些答案进行偏好排序(A 比 B 好)
  3. 训练一个奖励模型来学习人类的偏好判断
  4. 用强化学习让语言模型的输出向高奖励方向靠拢

奖励模型(Reward Model, RM)

奖励模型的任务是:给定一个问题 xx 和一个回答 yy,输出一个标量分数 rϕ(x,y)r_\phi(x, y),表示这个回答有多好。

训练数据是成对的偏好样本 (x,yw,yl)(x, y_w, y_l),其中 ywy_w 是被人类偏好的回答(winner),yly_l 是较差的回答(loser)。

训练目标采用 Bradley-Terry 偏好模型:

LRM=E(x,yw,yl)[logσ(rϕ(x,yw)rϕ(x,yl))]L_{RM} = -\mathbb{E}_{(x, y_w, y_l)} \left[ \log \sigma\left( r_\phi(x, y_w) - r_\phi(x, y_l) \right) \right]

直觉上:我们希望 rϕ(x,yw)>rϕ(x,yl)r_\phi(x, y_w) > r_\phi(x, y_l),两者差值越大越好,而 sigmoid 函数将差值转化为概率。

:::info 奖励模型的结构 通常将语言模型的最后一层替换为线性层,输出单个标量。奖励模型一般与被训练的语言模型大小相当或更大,以确保打分能力。 :::

PPO 算法:强化学习驱动的优化

有了奖励模型,下一步是用它来优化语言模型(称为 actor/policy)。PPO(Proximal Policy Optimization,近端策略优化)是目前最成熟的选择。

语言模型生成 token 的过程本质上是一个序列决策过程:

  • 状态(state):当前已生成的 token 序列
  • 动作(action):选择下一个 token(词表大小的离散空间)
  • 奖励(reward):回答结束时由 RM 给出的分数

PPO 的核心目标:最大化期望奖励,同时约束每次更新步幅不能太大:

LPPO=Et[min(πθ(atst)πθold(atst)A^t, clip(πθ(atst)πθold(atst),1ϵ,1+ϵ)A^t)]L_{PPO} = \mathbb{E}_t \left[ \min\left( \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)} \hat{A}_t,\ \text{clip}\left(\frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)}, 1-\epsilon, 1+\epsilon\right) \hat{A}_t \right) \right]

其中 A^t\hat{A}_t 是优势函数(Advantage function),衡量某个动作比平均水平好多少。

KL 散度惩罚:防止 Reward Hacking

一个严重问题:如果只优化 RM 的分数,模型会很快找到"走捷径"的方式——比如输出一堆看似流畅但毫无内容的废话,却恰好骗过了奖励模型。这种现象叫做 reward hacking(奖励黑客)。

解决方法:在奖励中加入 KL 散度惩罚,约束优化后的模型不能偏离 SFT 初始化太远:

rtotal(x,y)=rϕ(x,y)βKL[πθ(yx)πref(yx)]r_{total}(x, y) = r_\phi(x, y) - \beta \cdot \mathbb{KL}\left[\pi_\theta(y|x) \| \pi_{ref}(y|x)\right]

其中 πref\pi_{ref} 是 SFT 后的参考模型(冻结参数),β\beta 控制惩罚力度。KL 散度衡量两个分布之间的差异:

KL[PQ]=yP(y)logP(y)Q(y)\mathbb{KL}[P \| Q] = \sum_y P(y) \log \frac{P(y)}{Q(y)}

:::warning 实现的复杂性 完整的 RLHF-PPO 需要同时维护 4 个模型

  • Actorπθ\pi_\theta):被优化的语言模型,产生动作
  • CriticVψV_\psi):价值函数,估计状态的期望奖励
  • Referenceπref\pi_{ref}):SFT 模型,计算 KL 惩罚(冻结)
  • Reward Modelrϕr_\phi):打分模型(冻结)

这意味着在训练时需要 4 倍的显存,工程实现非常复杂。这直接催生了更简单的方法。 :::


17.2 DPO:直接偏好优化

核心洞见:RM 和最优策略之间的解析对应

2023 年,Stanford 的研究者发现了一个关键数学事实:在有 KL 约束的 RL 问题中,最优策略可以用奖励模型解析地表达出来

π(yx)=1Z(x)πref(yx)exp(1βr(x,y))\pi^*(y|x) = \frac{1}{Z(x)} \pi_{ref}(y|x) \exp\left(\frac{1}{\beta} r(x, y)\right)

其中 Z(x)=yπref(yx)exp(1βr(x,y))Z(x) = \sum_y \pi_{ref}(y|x) \exp\left(\frac{1}{\beta} r(x, y)\right) 是归一化常数。

反过来,这意味着奖励可以用策略来表达:

r(x,y)=βlogπ(yx)πref(yx)+βlogZ(x)r(x, y) = \beta \log \frac{\pi^*(y|x)}{\pi_{ref}(y|x)} + \beta \log Z(x)

直接优化偏好对

DPO(Direct Preference Optimization,直接偏好优化)的关键步骤:将上面的奖励表达式代入 Bradley-Terry 偏好模型,logZ(x)\log Z(x) 会在 ywyly_w - y_l相互抵消

最终得到一个不需要显式奖励模型的损失函数:

LDPO=E(x,yw,yl)[logσ(βlogπθ(ywx)πref(ywx)βlogπθ(ylx)πref(ylx))]L_{DPO} = -\mathbb{E}_{(x, y_w, y_l)} \left[ \log \sigma\left( \beta \log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)} - \beta \log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)} \right) \right]

直觉解释:

  • logπθ(ywx)πref(ywx)\log \frac{\pi_\theta(y_w|x)}{\pi_{ref}(y_w|x)}:好答案相对于参考模型被"抬高"了多少
  • logπθ(ylx)πref(ylx)\log \frac{\pi_\theta(y_l|x)}{\pi_{ref}(y_l|x)}:差答案相对于参考模型被"抬高"了多少
  • DPO 要求:好答案被抬高的幅度 > 差答案被抬高的幅度

RLHF vs DPO 对比

维度RLHF + PPODPO
模型数量4 个(actor/critic/ref/RM)2 个(policy/ref)
训练稳定性较难,超参数敏感稳定,接近监督学习
工程复杂度极高
在线采样支持(actor 持续生成新数据)不支持(离线数据集)
效果略优(特别是推理任务)接近,对话/无害性任务表现好
数据格式偏好对即可偏好对即可
# DPO 损失函数的核心实现(PyTorch 伪代码)
import torch
import torch.nn.functional as F

def dpo_loss(policy_logprobs_w, policy_logprobs_l,
ref_logprobs_w, ref_logprobs_l, beta=0.1):
"""
policy_logprobs_w: log π_θ(y_w|x)
policy_logprobs_l: log π_θ(y_l|x)
ref_logprobs_w: log π_ref(y_w|x)
ref_logprobs_l: log π_ref(y_l|x)
"""
log_ratio_w = policy_logprobs_w - ref_logprobs_w
log_ratio_l = policy_logprobs_l - ref_logprobs_l

logits = beta * (log_ratio_w - log_ratio_l)
loss = -F.logsigmoid(logits).mean()
return loss

:::tip DPO 的局限性 DPO 无法在线采样新数据——它只能在固定的偏好数据集上训练。而对于推理、数学等任务,我们往往希望模型能自己生成答案并从对错中学习。这个需求催生了 GRPO。 :::


17.3 GRPO 与推理模型训练

为什么需要新方法

数学解题和代码生成有一个 DPO 无法充分利用的特性:答案有明确的对错判断

  • 数学题:最终数值答案是否正确?
  • 代码:能否通过单元测试?
  • 逻辑推理:结论是否能从前提推出?

这些任务不需要人类标注员来判断好坏,可以用程序自动验证。更重要的是,我们可以实时生成数据——让模型对同一道题生成 GG 个答案,检验对错,然后立即用这些数据来训练。

GRPO 算法

GRPO(Group Relative Policy Optimization,组内相对策略优化)由 DeepSeek 团队提出。

核心步骤:

  1. 对同一问题 xx,用当前策略采样 GG 个答案 {y1,y2,...,yG}\{y_1, y_2, ..., y_G\}
  2. 用验证函数给每个答案打分:{r1,r2,...,rG}\{r_1, r_2, ..., r_G\}
  3. 组内归一化计算优势:
A^i=rimean(r1,...,rG)std(r1,...,rG)\hat{A}_i = \frac{r_i - \text{mean}(r_1,...,r_G)}{\text{std}(r_1,...,r_G)}
  1. 用归一化优势作为信号更新策略,同时保持 KL 约束
LGRPO=Ex1Gi=1G[min(πθ(yix)πold(yix)A^i, clip(,1±ϵ)A^i)βKL[πθπref]]L_{GRPO} = -\mathbb{E}_x \frac{1}{G}\sum_{i=1}^{G} \left[ \min\left( \frac{\pi_\theta(y_i|x)}{\pi_{old}(y_i|x)} \hat{A}_i,\ \text{clip}\left(\cdot, 1\pm\epsilon\right) \hat{A}_i \right) - \beta \cdot \mathbb{KL}[\pi_\theta \| \pi_{ref}] \right]

与 PPO 的关键区别:

GRPO 不需要 Critic 网络。PPO 的优势函数 A^t\hat{A}_t 依赖 Critic 来估计状态价值,而 GRPO 直接用组内相对奖励代替——同一批答案中,对的答案获得正优势,错的答案获得负优势。这将模型数量从 4 个减少到 2 个(policy + reference)。

:::info 可验证奖励的设计

典型的可验证奖励(Verifiable Reward)设计:

任务类型奖励信号
数学解题答案数值是否正确(+1/0)
代码生成测试用例通过数 / 总用例数
格式遵从是否符合要求的输出格式
逻辑推理结论是否从前提合法推出

奖励函数完全由程序判定,不依赖任何人工标注,因此可以无限扩展训练数据。 :::


17.4 o1 / R1 的慢思考范式

两种思维模式

心理学家 Kahneman 将人类思维分为两种:

  • System 1(快思考):直觉、自动、快速
  • System 2(慢思考):逻辑、审慎、耗时

传统语言模型类似 System 1——看到问题直接生成答案,没有中间推理过程。而 o1/R1 等推理模型模拟 System 2:先生成一段思维链(Chain-of-Thought),再给出最终答案。

Test-Time Compute:想得越久,答得越好

一个关键发现:给模型更多"思考时间"(即更长的推理 token 预算)可以显著提升答题质量

这种现象被称为 Test-Time Compute Scaling(测试时计算扩展)。与训练时扩展(更大模型、更多数据)不同,它在推理阶段投入计算资源:

答题质量f(训练参数量,训练数据量,推理时 token 数新维度)\text{答题质量} \approx f(\text{训练参数量}, \text{训练数据量}, \underbrace{\text{推理时 token 数}}_{\text{新维度}})

实验表明,一个较小的推理模型在足够长的思维链下,可以超越更大的直接回答模型。

DeepSeek-R1:纯 RL 训练出推理行为

DeepSeek-R1 的重要发现:不需要人工标注思维链,通过纯 RL 训练,模型可以自发学会推理行为

训练流程:

  1. 以 SFT 模型为起点
  2. 用 GRPO 在大量数学/代码题上训练(使用可验证奖励)
  3. 只要求最终答案正确,不约束中间推理过程
  4. 模型自然涌现出"先思考、再回答"的行为

:::info 涌现的推理行为

在训练过程中,DeepSeek-R1 自发出现了以下行为,这些行为从未被人工标注

  • 自我反思(Self-reflection):发现推理有误后主动回溯,例如"等等,我之前的计算似乎有问题……"
  • 验证(Verification):生成答案后自我检验,例如"让我验证一下这个结果是否代入原方程成立"
  • 多路径探索:尝试不同解法,比较哪种更简洁

这些行为的涌现说明:当奖励信号足够明确、训练数据足够丰富时,模型可以自己发现"思考"比"直接猜"更有效。 :::

R1 训练的关键设计

设计要素说明
奖励来源可验证任务(数学/代码),程序自动判断对错
优化算法GRPO,无需 Critic 网络,工程效率高
思维链格式使用 <think>...</think> 标记区分推理和答案
格式奖励额外奖励正确使用 <think> 标签的输出
数据扩展强模型生成思维链 → 蒸馏训练小模型(R1-Distill)
# R1 典型输出格式
用户:计算 √(2 + √(2 + √2)) 的近似值

助手:<think>
让我逐层计算。
最内层:√2 ≈ 1.4142
中间层:√(2 + 1.4142) = √3.4142 ≈ 1.8478
最外层:√(2 + 1.8478) = √3.8478 ≈ 1.9616

等等,让我验证:1.9616² ≈ 3.8479 ✓
</think>

√(2 + √(2 + √2)) ≈ **1.9616**

本章小结

方法核心思路模型数量数据需求适用场景
RLHF + PPO训练 RM,用 RL 优化策略4人工偏好标注通用对话,无害性
DPO将 RM 消去,直接优化偏好对2人工偏好标注对话,无害性,简单偏好
GRPO组内相对奖励,无需 Critic2可验证任务(自动)数学,代码,推理
GRPO + CoT纯 RL 涌现推理链2可验证任务(自动)复杂推理,慢思考模型

对齐训练的演进逻辑:RLHF 确立了用人类偏好优化模型的框架 → DPO 简化了实现,降低了工程门槛 → GRPO 利用可验证奖励摆脱了人工标注的瓶颈 → 慢思考范式开辟了"推理时扩展"这一全新的能力维度。


下一章我们将离开训练阶段,转向推理加速:当模型训练完成后,如何让它更快、更省地服务大量用户请求?这涉及 KV Cache 优化、量化、推测解码等一系列系统技术。