PPO:用强化学习微调语言模型的艺术与苦难

PPO 原本是为 Atari 游戏和机器人设计的。把它搬到语言模型上,就像把赛车引擎装到自行车上——强大但需要极其精细的调校才不会翻车。

为什么需要强化学习?

在前面的文章中,我们建好了一个”评委”——奖励模型。它能对任何 (问题, 回答) 打分。

现在的问题是:怎么用这个分数来改进模型?

直觉上你可能想:”对高分的回答做更多 SFT 不就行了?” 这叫 Best-of-N 或 Rejection Sampling——生成 N 个回答,选分最高的那个,用它做 SFT。这确实有效,但效率极低:大部分生成都被丢弃了,而且你无法利用”失败尝试”中的信息。

强化学习的优势在于:它不只奖励好的行为,还能从坏的行为中学习。PPO 在每一步生成时都获得梯度信号——不只是”最终答案好不好”,而是”每一步选择的方向对不对”。

PPO 的核心思想:高速公路上的护栏

PPO(Proximal Policy Optimization)的核心创新可以用一个比喻来理解:

想象你在一条高速公路上开车。你的目标是尽快到达终点(最大化奖励),但高速公路两侧有护栏。护栏不会减慢你的速度,但它们防止你因为转向过猛而冲出路面。

在传统的策略梯度方法(如 REINFORCE)中,没有护栏。每一步更新可能很大,如果方向稍微偏了,模型会突然崩溃——输出变成乱码、无限重复、或退化为固定模板。

PPO 的护栏就是 clipping 机制

Clipping 机制的数学

PPO 计算新旧策略之间的概率比:

\[r(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\text{old}}(a_t|s_t)}\]

当 $r(\theta) = 1$ 时,新旧策略完全一样。$r(\theta) > 1$ 意味着新策略对这个 action 更自信,$r(\theta) < 1$ 意味着新策略更不看好这个 action。

PPO 的目标函数限制了 $r(\theta)$ 的变化范围:

\[L^{\text{CLIP}} = \mathbb{E}\left[\min\left(r(\theta) \cdot A_t, \; \text{clip}(r(\theta), 1-\epsilon, 1+\epsilon) \cdot A_t\right)\right]\]

其中 $\epsilon$ 通常是 0.1-0.2,$A_t$ 是优势函数(advantage,衡量这个 action 比平均水平好多少)。

直觉解释:

  • 如果一个 action 是好的($A_t > 0$),PPO 允许增加它的概率,但增幅上限是 $(1+\epsilon)$ 倍——不能一步到位全压上去
  • 如果一个 action 是坏的($A_t < 0$),PPO 允许降低它的概率,但降幅下限是 $(1-\epsilon)$ 倍——不能一步就完全排除

这就是护栏:你可以在正确的方向加速,但每一步的转向幅度有限。

PPO Clipping: 策略更新的护栏 r(θ) = π_new / π_old 目标函数值 1.0 1-ε 1+ε 无 clip 被 clip 的区域 (梯度为 0,停止更新) 正常优化区域 (A > 0 的情况) 超过 1+ε 时梯度被截断 → 防止过度自信的更新

RLHF 中的四模型系统

PPO 在 RLHF 中的完整实现需要同时维护四个模型

模型 作用 是否更新
策略模型 (Actor) 生成回答 ✓ 持续训练
参考模型 (Reference) 计算 KL 惩罚 ✗ 冻结的 SFT 模型
奖励模型 (Reward) 给回答打分 ✗ 已训练好,冻结
价值模型 (Critic) 估计期望奖励 ✓ 持续训练

为什么需要价值模型(Critic)?

策略梯度的一个基本问题是方差太大。如果一个回答得了 8 分,你怎么知道这是好还是坏?如果平均水平是 3 分,8 分就很好;如果平均水平是 9 分,8 分就是失败。

价值模型 $V(s)$ 就是用来估计”平均水平”的。它预测从当前状态开始,未来能获得的期望奖励。有了它,你可以计算优势(Advantage)

\[A_t = R_t - V(s_t)\]

“这个行为比我预期的好多少”——这才是策略应该关注的信号。

KL 惩罚:保险绳

除了 clipping 护栏,RLHF-PPO 还有第二道安全机制:KL 散度惩罚。

\[R_{\text{total}} = R_{\text{reward}}(x, y) - \beta \cdot \text{KL}(\pi_\theta \| \pi_{\text{ref}})\]

KL 散度衡量新策略和参考模型(冻结的 SFT 模型)之间的”距离”。如果新策略开始生成和原模型完全不同的东西,KL 惩罚会拉住它。

比喻: Clipping 是每一步的护栏(限制单步更新幅度),KL 惩罚是全局的保险绳(限制累计偏离程度)。两者配合,确保模型在追求高奖励的同时不会”迷失自我”。

$\beta$ 通常设为 0.05-0.2。太小了,模型会 reward hack;太大了,模型完全不学习。

为什么 PPO 在 LLM 上是”调参地狱”?

问题 1:训练不稳定

四个模型必须同步训练。策略改进 → 价值函数跟不上 → 优势估计不准 → 策略更新方向错误 → 训练崩溃。

超参数之间的相互耦合也很严重:

  • 学习率影响 clipping 是否被触发
  • KL 系数影响策略能探索多远
  • PPO epoch 数影响每 batch 数据的利用率
  • GAE λ 影响长期 vs 短期信号的权重

改动任何一个,其他参数的最优值都会变化。

问题 2:奖励黑客

PPO 是一个强大的优化器。如果给它足够多的步数和足够小的 KL 约束,它一定会找到奖励模型的漏洞。典型症状:

  • 训练初期:奖励上升,回答质量确实在改善
  • 中期:奖励继续上升,但人类评估分数开始停滞
  • 后期:奖励飙升,但回答变得冗长、谄媚、格式化——RM 给高分,人类觉得恶心

这就是那条著名的”overoptimization 曲线”:proxy reward 持续上升,但 gold reward(真实人类偏好)先升后降。

问题 3:模式坍塌

如果 KL 约束太弱,模型会收敛到一个狭窄的输出分布——对所有问题都用类似的模板回答。多样性和创造力消失,模型变成一个只会说”八股文”的应试机器。

问题 4:计算成本

对一个 70B 参数的模型做 PPO,需要同时在 GPU 上维护:

  • 70B 策略模型
  • 70B 参考模型(冻结但占内存)
  • 70B 价值模型
  • 6-70B 奖励模型

总计 200-300B 参数的显存占用。即使用混合精度和梯度累积,这也需要数百张 GPU 和数周的训练时间。

PPO 的训练循环

每一步 PPO 更新的完整流程:

for each batch of prompts:
    1. 策略模型生成回答 (rollout)
    2. 奖励模型给回答打分
    3. 参考模型计算 KL 散度
    4. 计算总奖励 = RM 分数 - β·KL
    5. 价值模型估计每个 token 位置的 V(s)
    6. 用 GAE 计算 Advantage
    7. 做 K 轮 PPO 更新(通常 K=1-4):
       - 计算概率比 r(θ)
       - 计算 clipped 目标
       - 更新策略模型
       - 更新价值模型
Prompt x 策略 π_θ 生成回答 y 奖励模型 RM → r(x,y) 参考模型 π_ref → KL(π_θ||π_ref) 价值模型 V → baseline 计算 Advantage A = R - β·KL - V (GAE 平滑) PPO Clip 更新 更新策略参数 → 生成新回答 → 循环

成功的 PPO 训练是什么样的

一个健康的 RLHF-PPO 训练曲线通常表现为:

  • 奖励分数:稳步上升,然后趋于平稳(不是飙升)
  • KL 散度:缓慢增长,稳定在 5-15 nats 之间
  • 人类偏好胜率:持续提升(vs SFT baseline)
  • 回答长度:微增但不爆炸
  • 困惑度(PPL):轻微上升但不崩溃

如果你看到奖励飙升但 KL 爆炸,或者奖励上升但回答长度翻倍——都是 reward hacking 的信号。

实践中的关键超参数

参数 典型值 含义
ε (clip) 0.1-0.2 单步更新幅度限制
β (KL) 0.05-0.2 偏离参考模型的惩罚强度
学习率 1e-6 ~ 5e-6 比 SFT 更小
PPO epochs 1-4 每批数据重复利用次数
Batch size 32-512 prompts 越大越稳定
GAE λ 0.95 优势估计的时间折扣
生成长度 256-2048 tokens 回答的最大长度

下一篇预告

PPO 强大但复杂:四个模型、大量超参数、训练不稳定、计算成本高昂。自然的问题是:能不能更简单?

2023 年,一篇论文给出了惊人的回答:不需要奖励模型,不需要 PPO,不需要价值函数——只用一个简单的分类损失,就能达到几乎相同的效果。这就是 DPO(Direct Preference Optimization)。而 2024 年 DeepSeek 更进一步:保留 RL 的探索能力,但砍掉价值函数——这就是 GRPO。下一篇,我们看看这些”后 PPO”时代的方法如何优雅地简化对齐训练。