PPO 算法详解:RLHF 中的核心优化器
PPO(Proximal Policy Optimization)是目前 RLHF 中最常用的强化学习算法。它的核心创新是通过裁剪机制限制策略更新幅度,让训练过程既高效又稳定。
从策略梯度说起
PPO 属于策略梯度(Policy Gradient)家族。理解 PPO 需要先理解策略梯度的基本思想:
策略梯度的核心思路:
1. 用当前策略生成一批动作(在 RLHF 中是生成回答)
2. 环境给出奖励(在 RLHF 中是奖励模型打分)
3. 让"好动作"的概率增大,"坏动作"的概率减小
参数更新方向:
∇J(θ) = E[∇log π_θ(a|s) · A(s,a)]
π_θ(a|s):策略在状态 s 下选择动作 a 的概率
A(s,a):优势函数(这个动作比平均好多少)
问题在于:步子迈太大,策略可能崩溃。
为什么需要裁剪?
普通策略梯度有一个致命缺陷:如果某次更新步幅过大,新策略可能比旧策略差很多,而且无法恢复。
灾难性更新示例:
旧策略: P("好回答") = 0.7
某次更新后: P("好回答") = 0.1 ← 一步跨太大,策略崩溃
后果:
- 生成的回答质量暴跌
- 奖励信号变得不可靠
- 后续训练全部失效
PPO 的裁剪机制
PPO 通过裁剪比率 r(θ) 来限制更新幅度:
import numpy as np
def ppo_loss(ratio, advantages, clip_epsilon=0.2):
"""
ratio: 新策略概率 / 旧策略概率 = π_new(a|s) / π_old(a|s)
advantages: 优势函数值 A(s,a)
clip_epsilon: 裁剪范围(通常 0.2)
"""
# 裁剪后的目标函数
clipped = np.clip(ratio, 1 - clip_epsilon, 1 + clip_epsilon)
# 取两者中较小的(保守估计)
loss = -np.minimum(ratio * advantages, clipped * advantages)
return loss.mean()
直觉解释:当 ratio 偏离 1 超过 0.2 时,裁剪会阻止进一步的更新,防止步幅过大。
PPO 的完整算法流程
PPO 训练循环:
1. 用当前策略收集一批数据(状态、动作、奖励)
2. 计算优势函数 A(s,a)(用 GAE 广义优势估计)
3. 迭代 K 轮(通常 K=3~10):
for each mini-batch:
计算新旧策略比率 r(θ) = π_new / π_old
计算裁剪目标: L = min(r*A, clip(r, 1-ε, 1+ε)*A)
反向传播更新 θ
4. 回到步骤 1,用新策略收集新数据
PPO 在 RLHF 中的角色
在 RLHF 流程中,PPO 是第三阶段的核心算法:
| RLHF 组件 | PPO 中的对应 |
|---|---|
| 语言模型 | 策略网络 π_θ |
| 生成的回答 | 动作 a |
| 当前上下文 | 状态 s |
| 奖励模型打分 | 奖励 r |
| SFT 模型 | 参考策略 π_ref(用于 KL 惩罚) |
RLHF 中的奖励设计:
总奖励 = 奖励模型分数 - β × KL散度(π_θ || π_ref)
β × KL散度 项的作用:
防止模型偏离 SFT 模型太远
避免"钻空子":模型不会为了获得高分而生成奇怪文本
PPO 的稳定性优势
对比其他策略梯度算法:
| 算法 | 步幅控制 | 样本效率 | 稳定性 |
|---|---|---|---|
| REINFORCE | 无 | 低 | 差 |
| TRPO | 信赖域约束 | 中 | 好(但计算复杂) |
| PPO | 裁剪机制 | 高 | 好(且计算简单) |
实践中的注意事项
- 裁剪范围 ε:通常设为 0.2,过大则更新太保守,过小则退化为普通策略梯度
- 优势函数估计:使用 GAE(λ=0.95)平衡偏差与方差
- KL 惩罚系数 β:太小则模型漂移,太大则模型无法改善
- 批量大小:通常需要较大的 batch(如 512~2048)以保证训练稳定
总结
PPO 通过简洁的裁剪机制解决了策略梯度训练不稳定的问题。在 RLHF 中,PPO 负责根据奖励模型的反馈优化语言模型的生成策略,同时通过 KL 惩罚确保模型不会偏离原始能力太远。它的高效和稳定使其成为当前 RLHF 的默认选择。
延伸阅读:DPO:跳过奖励模型的直接偏好优化