前文梳理了策略梯度定理与 PPO 的基础推导,这里从 PPO 接着往后讲:DPO 如何把强化学习变成一个分类损失,GRPO 又如何去掉价值网络、改用同一题组内采样的相对优势。
大模型后训练全景
预训练学的是“续写”,后训练要它学会“按人想要的方式回答”。现在的主流顺序是先 SFT,再做偏好优化或强化学习。
RM + PPO(InstructGPT)
DPO 系(离线偏好对)
GRPO 系(可验证奖励,R1)
三条路要解决同一个问题:SFT 只告诉模型“这个答案对”,没告诉它“这个比那个好多少”,也没法让模型从自己生成的答案里学习。
PPO 回顾:放到大模型里是什么样
传统的 PPO 多用于 CartPole、Atari 那种环境。换到大模型上,对应关系是这样:
| RL 概念 | 在 LLM 里 |
|---|---|
| 状态 $s_t$ | prompt + 已经生成的前 $t$ 个 token |
| 动作 $a_t$ | 下一个 token(动作空间 = 词表,十几万) |
| 策略 $\pi_\theta$ | 正在训练的大模型本身 |
| 奖励 | 整段回答生成完才有一个分数(奖励模型给),中间每个 token 只有 KL 惩罚 |
| 一条轨迹 | 一次完整回答 |
RLHF-PPO 显存里要放 4 个模型
- Policy(Actor):被训练的模型。
- Reference:SFT 后的冻结副本,算 KL,防止模型跑偏到胡言乱语。
- Reward Model:用人类偏好对训练出来的打分模型,冻结。
- Value Model(Critic):估计每个位置的 $V(s)$,用来算优势,也要训练。通常和 policy 一样大。
每个 token 的奖励写成:
优势 $A_t$ 用 GAE 从 critic 的 $V$ 值算出来,然后套 PPO 的裁剪目标:
一句话记:好动作($A>0$)概率最多涨到 $1+\varepsilon$,坏动作($A<0$)最多压到 $1-\varepsilon$,再往外梯度为零。这样一批数据可以重复用几轮而不把策略推得太远。
DPO:不训练奖励模型,也不做采样
DPO(Rafailov 等,2023)的出发点:带 KL 约束的 RLHF 目标,最优策略其实有解析解。
三步推导
- RLHF 目标是“最大化奖励,同时 KL 别离参考模型太远”。它的最优解是:
$$\pi^*(y\mid x)=\frac{1}{Z(x)}\,\pi_{\text{ref}}(y\mid x)\exp\!\Big(\frac{1}{\beta}r(x,y)\Big)$$
- 反过来,奖励可以用策略表示:
$$r(x,y)=\beta\log\frac{\pi^*(y\mid x)}{\pi_{\text{ref}}(y\mid x)}+\beta\log Z(x)$$
$Z(x)$ 算不出来,但它只跟 $x$ 有关。
- 人类偏好用 Bradley-Terry 模型:$P(y_w \succ y_l) = \sigma(r_w - r_l)$。两条回答相减,$Z(x)$ 正好消掉,得到 DPO 损失:
$$\mathcal{L}_{\text{DPO}}=-\log\sigma\Big(\beta\Big[\log\frac{\pi_\theta(y_w\mid x)}{\pi_{\text{ref}}(y_w\mid x)}-\log\frac{\pi_\theta(y_l\mid x)}{\pi_{\text{ref}}(y_l\mid x)}\Big]\Big)$$
所以 DPO 本质上是一个二分类损失:让模型对“好回答”的相对概率涨得比“坏回答”多。只需要 policy 和 reference 两个模型,数据是现成的 (prompt, chosen, rejected) 三元组。
Δ 是括号里那一项:好回答的对数概率比减去坏回答的。Δ 已经很大时权重趋近 0,模型基本不再管这对样本;Δ 为负(模型把两者排反了)时权重接近 1,梯度最大。β 越大,越快“学满”,模型也更贴近参考模型。
- 离线:只在给定偏好对上学,模型自己生成的新回答没被评过,分布一偏就失效。
- chosen 的概率也可能下降:损失只要求两者差距变大,两个一起降、rejected 降得更多也满足。实践中常见。
- 长度偏好:长回答对数概率之和更负,容易学出“越长越好”或反过来的怪偏好。
常见变体:各自改了哪一点
| 方法 | 改了什么 | 要参考模型吗 |
|---|---|---|
| IPO | 把 $-\log \sigma$ 换成平方损失,$\Delta$ 拉到一个固定目标值就停,防止在偏好对上过拟合 | 要 |
| KTO | 不需要成对数据,单条样本标“好/坏”就能训,借了前景理论的损失形状 | 要 |
| ORPO | SFT 损失 + 一个 odds ratio 惩罚项,SFT 和对齐一步做完 | 不要 |
| SimPO | 用长度归一化后的平均对数概率当隐式奖励,加一个目标间隔 $\gamma$ | 不要 |
GRPO:去掉 critic,用同一题的多个回答互相比较
GRPO 出自 DeepSeekMath(2024),DeepSeek-R1(2025)用它把推理能力练了出来,之后成了“推理模型 RL”的默认起点。
核心想法
PPO 需要 critic 来估计“这个状态本来值多少分”,作为优势的基线。GRPO 换了个基线:同一个问题采样 $G$ 个回答(比如 8 个),用这一组的平均分当基线。
这个优势赋给第 $i$ 个回答里的每一个 token。比组平均好的回答,所有 token 概率往上推;比平均差的往下压。然后照搬 PPO 的裁剪目标,KL 不再加进奖励,而是直接加在损失里:
KL 用的估计式是 $\frac{\pi_{\text{ref}}}{\pi_\theta} - \log\frac{\pi_{\text{ref}}}{\pi_\theta} - 1$,恒非负,逐 token 就能算。
可以观察到两件事:答对的越少,答对的那几个拿到的正优势越大,这正是“难题上做对了要重奖”;全对或全错时,组内标准差为 0,所有优势都是 0(实现里分母加了 $\varepsilon$),这道题没有梯度,白白花了采样算力。后面 DAPO 的动态采样就是针对第二点。
奖励从哪来:可验证奖励(RLVR)
R1 没用神经网络奖励模型,用的是规则:数学题比对最终答案,代码题跑单元测试,再加一个格式奖励(思考过程是否放在规定的标签里)。规则奖励没法被“讨好”,reward hacking 少很多。R1-Zero 甚至跳过 SFT,直接在基座上做 GRPO,回答长度和自我检查行为是训练中自己长出来的。
GRPO 之后的修补(2025)
| 方法 | 发现的问题 | 改法 |
|---|---|---|
| Dr. GRPO | 按回答长度 $1/|o_i|$ 平均,错误的长回答每个 token 被罚得轻,模型越错越啰嗦;除以 std 让过易、过难的题权重偏高 | 去掉长度归一化和 std 归一化 |
| DAPO | 熵塌缩、全对全错的组浪费算力、长回答被截断时奖励有噪声 | 裁剪上下限分开(clip-higher)、过滤全对全错的组(动态采样)、token 级损失、超长惩罚;去掉 KL |
| GSPO | token 级重要性比方差大,MoE 模型上尤其不稳 | 重要性比和裁剪都改到整条序列层面(Qwen3 团队) |
四种方法对比
| 对比维度 | SFT | RLHF-PPO | DPO | GRPO |
|---|---|---|---|---|
| 需要的模型 | 1 | 4(policy, ref, RM, critic) | 2(policy, ref) | 2 + 奖励函数(policy, ref;ref 可省) |
| 数据 | 标准答案 | prompt + 偏好对训 RM | (prompt, chosen, rejected) | prompt + 能判对错的规则 |
| 在线采样 | 否 | 是 | 否 | 是,每题 G 个 |
| 基线 / 优势 | — | critic + GAE | 隐式奖励差 | 组内均值与标准差 |
| 适合场景 | 学格式、学领域知识 | 通用对齐,资源充足 | 风格、语气、安全这类偏好 | 数学、代码、能自动判分的任务 |
| 常用框架 | LLaMA-Factory / TRL | LLaMA-Factory / OpenRLHF | LLaMA-Factory(支持 DPO / KTO / ORPO / SimPO) | TRL GRPOTrainer / verl / OpenRLHF |
在线 RL(PPO / GRPO)训练时,采样(rollout)是自回归一个 token 一个 token 生成,GRPO 还要每题生成 $G$ 个回答,耗时往往占整轮训练的大半。因此 verl、OpenRLHF 会把采样交给 vLLM 这类推理引擎,训练用 FSDP / DeepSpeed,两边同步权重。
工程延伸:从 SFT 到 DPO 的配置与选型
以“文本润色改写”这类任务为例,如果已经做完了 SFT 并配有自动评测裁判(按意思、事实、上下文判是否过关),可以顺着三步把流程延伸到 DPO:
- 同一条输入,让 SFT 后的模型采样几个润色版本。
- 用评测裁判打分,过关的当
chosen,不过关的当rejected,凑成偏好对。 - 在 LLaMA-Factory 中把
stage从sft改成dpo,其他 QLoRA 配置基本不动。
# 在原有的 QLoRA SFT 配置上改这几行即可切换到 DPO
stage: dpo
pref_beta: 0.1
pref_loss: sigmoid # 标准 DPO;也可选 orpo / simpo
dataset: polish_pref # dataset_info.json 里设 "ranking": true,列 chosen / rejected
learning_rate: 5.0e-6 # 比 SFT 小一个量级左右
为什么这类任务选 DPO 而不是 GRPO:润色好不好没有唯一正确答案,没法写规则判分;而裁判给的“过 / 不过”天然能凑成偏好对。反过来,如果任务是“从订单数据里算出某个数”,答案能自动核对,就更适合 GRPO。
读者怎么说
先看读者反馈,再直接在当前页面继续讨论。不用绑定社交账号,填个昵称、抓一只娃娃就能留言。
快捷身份
留下你的想法
选一个预设身份,或者直接填昵称;写完点发布,抓到指定的娃娃就能提交。若显示“需要配置 Waline”,说明站点还缺少可写评论后端。
当前未选择预设身份