PPO 完全指南:从 TRPO 到工程落地
一、背景:PPO 从哪里来?
PPO 的前身是 TRPO(Trust Region Policy Optimization)。要理解 PPO 为什么这样设计,必须先理解 TRPO 想解决什么问题。
TRPO 的核心思想
强化学习中,策略梯度方法的核心问题是:每次更新步子多大合适?
步子太小 → 收敛慢;步子太大 → 策略崩溃,难以恢复。
TRPO 的解法是:在优化目标的同时,加一个硬约束,限制新旧策略的 KL 散度不超过阈值 。
TRPO 能理论保证策略单调改进,但代价沉重:
- 需要计算 Fisher 信息矩阵的逆,计算量是参数量的平方级
- 需要共轭梯度迭代求解约束优化
- 大模型参数动辄几十亿,完全不可行
PPO 的核心改动
PPO 用一个极其简单的想法替代了 TRPO 的二阶约束:
直接把概率比值截断(clip)在 的范围内,从而限制策略更新幅度。
TRPO 的约束是在参数空间上控制 KL 距离( 是 KL 散度上界);PPO 的 是在概率比值空间上直接截断,两者度量体系不同,不能直接比大小。典型取值:,。
PPO 牺牲了理论上的严格保证,换来了一阶优化、标准反向传播,工程实现大幅简化。
二、PPO 公式详解
2.1 核心目标函数
逐符号解释:
| 符号 | 含义 |
|---|---|
| Actor(策略网络)当前参数 | |
| 对一批采样数据取期望(均值) | |
| 概率比率 = ,衡量新旧策略对同一动作的概率之比 | |
| 优势函数估计值,表示动作 比”平均水平”好多少 | |
| 截断超参,控制更新幅度,典型值 | |
| 将 强制限制在 范围内 |
2.2 为什么是 clip + min,而不只是 clip?
这是 PPO 设计中最精妙的地方,单独用 clip 是不够的。
场景一:优势 (好动作,应该增大概率)
- 时:clip 强制截断,梯度为零,不再继续增大比率 ✓
- 时:min 取 (未截断值更小),仍允许向好方向移动 ✓
场景二:优势 (坏动作,应该减小概率)
- 时:clip 强制截断,梯度为零,不再继续减小比率 ✓
- 时(概率不降反升!):
- 此时 是很负的值
- 被截断,是一个”没那么负”的值
- min 会选更负的那个,即 ,产生梯度,强迫把比率拉回来 ✓
结论:clip 负责”别走太远”,min 负责”走错了必须拉回来”,二者缺一不可。
2.3 完整损失函数
| 项 | 含义 | 作用 |
|---|---|---|
| Actor 策略损失 | 优化动作选择 | |
| Critic 价值损失(MSE) | 训练价值估计更准确 | |
| 策略熵 | 鼓励探索,防止策略过早收敛 | |
| 权重系数 | 平衡各项损失 |
2.4 优势函数:GAE
PPO 通常使用 GAE(Generalized Advantage Estimation) 来估计 :
- :TD 残差,是单步优势的估计
- :折扣因子,控制未来奖励的权重
- :GAE 平滑系数,控制方差和偏差的权衡
三、PPO 的系统架构
在大语言模型的 RLHF(基于人类反馈的强化学习)场景中,PPO 同时需要维护 4 个模型:
1 | query (q) |
四个模型的角色
| 模型 | 是否训练 | 作用 |
|---|---|---|
| Actor(策略网络) | ✅ 是 | 生成回答,是训练的最终目标 |
| Critic(价值网络) | ✅ 是 | 估计当前状态价值 ,计算 GAE,训练完可丢弃 |
| Reference Model | ❌ 冻结 | SFT 初始模型,计算 KL 散度,防止 Actor 跑偏 |
| Reward Model | ❌ 冻结 | 人类偏好训练的打分模型,给每条输出打分 |
KL 惩罚机制:
Reference Model 保证了 Actor 不会为了刷高奖励分而产生”奖励黑客”——说出毫无意义但高分的奇怪输出。
四、核心代码讲解
1 | import torch |
关键实现细节
① old_log_probs 必须 detach
old_log_probs 是在数据采集(rollout)阶段用旧策略计算的,它是常数基准,不应该有梯度。如果不 detach,PyTorch 会尝试对它反向传播,导致错误或无意义的梯度。
② 对数差 vs 直接相除
1 | # ❌ 直接相除:数值不稳定 |
当概率值非常小(如 )时,直接相除会有浮点精度问题;对数空间做减法再取指数则稳定得多。
③ advantages vs returns 的区别
| 变量 | 公式 | 用途 |
|---|---|---|
advantages |
GAE | 告诉 Actor”这个动作比均值好多少”,用于更新策略 |
returns |
告诉 Critic”这个状态的真实价值是多少”,用于更新价值估计 |
五、PPO 的缺点
PPO 虽然工程简洁、效果稳定,但在大语言模型场景下暴露出明显短板:
1. 显存压力极大
同时需要加载 4 个大模型(Actor、Critic、Reference、Reward),且 Actor 和 Critic 通常与原始 LLM 同等体量。以 7B 参数模型为例:
仅模型权重就需要 56GB,还不含激活值、优化器状态,实际需求轻松超过 160GB。
2. On-Policy 导致训练效率低
PPO 是 On-Policy 算法:每次用当前策略生成数据,更新几步后数据就过期,必须重新采样。
1 | 生成 → 训练几步 → 数据过期 → 重新生成 → 训练几步 → ... |
对于 LLM 而言,生成是自回归的,速度远慢于训练。生成成为整个训练流程的瓶颈。
3. Critic 训练带来额外复杂性
Critic 需要与 Actor 同步训练,且本身也是一个 LLM 级别的大模型。如果 Critic 估值不准,会导致 GAE 偏差,进而污染 Actor 的训练信号。
4. 超参数敏感
PPO 有多个超参数需要精心调整:clip 系数 、Critic 系数 、熵系数 、GAE 的 、KL 惩罚系数 ……各超参之间存在耦合,调参成本高。
六、后续改进方向
针对 PPO 的上述缺点,学界提出了几个有影响力的改进方案:
| 算法 | 核心改动 | 解决的问题 |
|---|---|---|
| ReMax | 用 REINFORCE + 贪心基线替代 GAE | 去掉 Critic,减少显存 |
| RLOO | 组内多条输出互为基线 | 去掉 Critic,基线更稳定 |
| GRPO | 组内平均奖励做基线,去掉 Critic | 去掉 Critic,只需 Actor + Reference,DeepSeek-R1 采用 |
其中 GRPO 目前最为流行。其优势函数估计为:
对同一个 query 采样 条输出,组内标准化得到优势,完全绕开了 Critic 模型。
总结
| 维度 | TRPO | PPO | GRPO |
|---|---|---|---|
| 约束方式 | KL 散度硬约束 | clip 截断 | clip + 组内基线 |
| 优化阶数 | 二阶(共轭梯度) | 一阶(Adam) | 一阶(Adam) |
| 所需模型数 | 2 | 4 | 2 |
| 工程复杂度 | 高 | 中 | 低 |
| 理论保证 | 单调改进 | 近似保证 | 无严格保证 |
| 大模型适用性 | 差 | 可用 | 好 |
PPO 是强化学习工程化落地的重要里程碑,理解它的公式逻辑(clip + min 的协同)、架构设计(四模型分工)和代码实现,是进入大模型 RLHF 领域的必要基础。
take home message:
「源码解析」合集:本文与 TRPO 解析:从数学原理到代码实现、MiniMind 源码阅读与架构分析 同属一个系列。建议先读 TRPO 那篇,PPO 的所有设计都是对它的工程简化。