第 29 天 · 一个 clip,让策略梯度既稳又好写
一句话
PPO 用一个裁剪后的替代目标限制每次策略更新的幅度,稳定性接近 TRPO,却只需要一阶优化。同一批数据可以训练多轮,实现只比普通策略梯度多几行代码,因此成为强化学习和 RLHF 的默认算法。
论文讲了什么
策略梯度(policy gradient)方法有一个老问题:步子迈大了,策略会崩。一次更新过猛,智能体开始采到更差的数据,之后很难恢复。2015 年的 TRPO 用 KL 散度约束限制更新幅度,但需要共轭梯度和二阶近似,实现复杂。它也不兼容含噪声的结构(例如 dropout)和策略与价值共享参数的网络。
PPO 的做法是只改目标函数。先定义新旧策略的概率比:
r_t(θ) = π_θ(a_t | s_t) / π_old(a_t | s_t)
再定义裁剪替代目标(clipped surrogate objective):
L_CLIP = E[ min( r_t · A_t, clip(r_t, 1 − ε, 1 + ε) · A_t ) ]
A_t 是优势函数的估计值,表示这个动作比平均水平好多少。这个目标的直觉如下:
- A_t > 0(好动作):目标鼓励增大它的概率。r_t 超过 1 + ε 后,目标不再增加。
- A_t < 0(坏动作):目标鼓励减小它的概率。r_t 低于 1 − ε 后,目标不再增加。
- 取 min 让目标成为未裁剪目标的下界。策略往变差的方向走时,裁剪不提供保护,照样受到惩罚。
因为每次更新的收益有上限,同一批采样数据可以安全地跑多轮小批量 SGD。论文在 MuJoCo 实验中每次采 2048 步,训练 10 轮,小批量大小 64,Adam 学习率 3 × 10^(−4)。
完整目标还有两项:价值函数的平方误差(系数 c1)和策略熵奖励(系数 c2)。这对应演员-评论家(actor-critic)结构。优势函数用 GAE 估计,λ = 0.95,γ = 0.99。
关键实验结果有 3 组:
- 目标函数对比:在 7 个 MuJoCo 任务上,ε = 0.2 的裁剪目标归一化平均分最高,为 0.82。不裁剪也不加惩罚的版本得 −0.39,比随机策略还差。自适应 KL 惩罚的最好成绩是 0.74。
- 连续控制:PPO 在几乎所有任务上超过 TRPO、A2C、CEM 和普通策略梯度。论文还用 PPO 训练 3D 人形机器人奔跑、转向和摔倒后爬起。
- Atari 49 个游戏:按整个训练过程的平均奖励,PPO 赢 30 个,ACER 赢 18 个,A2C 赢 1 个。按最后 100 局的平均奖励,ACER 赢 28 个,PPO 赢 19 个。PPO 学得更快,ACER 最终分数略高,但 PPO 的实现简单得多。
关键概念
- 策略梯度(Policy gradient)
- 直接对策略参数求期望回报的梯度,提高优势为正的动作的概率。它不需要环境模型,但梯度方差大,对步长很敏感。
- 概率比(Probability ratio)
- 记作 r_t:新策略与采样时的旧策略给同一个动作的概率之比。r_t = 1 表示策略没有变化。它也是重要性采样的权重。
- 裁剪替代目标(Clipped surrogate objective)
- 把 r_t 限制在 [1 − ε, 1 + ε],再与未裁剪项取较小值。效果是:策略在改进方向上偏离旧策略超过 ε 后,梯度变为 0。
- 优势函数(Advantage function)
- <code>A(s, a) = Q(s, a) − V(s)</code>,表示动作 a 比该状态下的平均水平好多少。用它代替原始回报,能显著降低梯度方差。
- 广义优势估计(Generalized Advantage Estimation, GAE)
- 把多步时序差分误差按 (γλ)^k 加权求和,用来估计优势。λ 在 0 到 1 之间调节:λ = 0 时偏差大,λ = 1 时方差大。
- 演员-评论家(Actor-critic)
- 演员网络输出动作分布,评论家网络估计状态价值 V(s)。评论家提供基线来计算优势。两个网络可以共享主干,PPO 的目标函数允许这样做。
历史位置:为什么值得读
PPO 出自 OpenAI。第一作者 John Schulman 也是 TRPO(2015)和 GAE(2015)的第一作者。可以把 PPO 看作他把 TRPO 的“信任域”思想压缩成一行目标函数的结果。
PPO 发表后很快成为 OpenAI 的默认强化学习算法。OpenAI Five 用大规模 PPO 训练 Dota 2 智能体,2019 年击败了世界冠军战队 OG。2022 年的 InstructGPT 用 PPO 依据奖励模型微调 GPT-3,ChatGPT 沿用了同一套流程。
后续研究也揭示了 PPO 的另一面。2020 年,Engstrom 等人发现,PPO 相对 TRPO 的优势有很大一部分来自代码层面的技巧,例如价值函数裁剪、奖励缩放、学习率退火和观测归一化。这些细节在论文正文里没有写全。
在清单里,第 27 天 Legg 把智能定义为在环境中拿奖励的能力,PPO 是实际拿奖励的主力算法。第 30 天的 RLHF 原论文用 A2C 和 TRPO 优化策略。后来把 RLHF 用到语言模型时,它们被换成了 PPO。
学前准备
- 懂马尔可夫决策过程:状态、动作、奖励、折扣回报
- 知道 REINFORCE 或基本策略梯度的公式
- 会用 PyTorch 写网络和自定义损失函数
- 了解 KL 散度衡量什么
在原仓库怎么学
- README.md:看本日的内容安排和文件清单。
- setup.py:运行它,检查依赖是否可用。
- implementation.py:按顺序读 4 个部分。ActorCritic 是演员和评论家网络。RolloutBuffer 存储轨迹并计算 GAE。ppo_loss 组合裁剪目标、价值损失和熵奖励。PPOAgent 实现训练循环。
- train_minimal.py:先用 CartPole-v1 跑通,再换 LunarLander-v2。
- data/README.md:了解训练日志 CSV 的列和模型检查点的保存位置。
- visualization.py:画 3 张诊断图:学习曲线、裁剪比例随训练的变化、策略熵随训练的变化。
- notebook.ipynb:在笔记本里逐步运行上面的流程。
- exercises/:做 5 个练习,依次是裁剪损失、GAE、演员-评论家网络、ε 消融实验、PPO 与普通策略梯度对比。答案在 exercises/solutions/。
今天再看
2026 年,PPO 仍是强化学习的基准算法。在大语言模型里,它的位置在变化:
- RLHF 的成本问题:InstructGPT 式的 PPO 训练需要同时加载 4 个模型:策略、参考模型、奖励模型、价值模型。显存和调参成本都很高。
- DPO(2023)绕开强化学习,直接用偏好数据优化策略。在很多对齐场景里,它取代了 PPO。
- GRPO(2024)出自 DeepSeekMath 论文。它保留 PPO 的裁剪概率比,去掉价值网络,用同一道题多个回答的相对得分当作优势。DeepSeek-R1 用它训练推理能力。
另一条延续是可验证奖励的强化学习:数学题看答案对错,代码看测试是否通过。这类训练的算法骨架仍然是 PPO 家族,裁剪概率比这个核心设计一直被大规模使用。
容易卡住的地方
- 用当前策略算旧概率:π_old 的对数概率必须在采样时记录并 detach。如果每轮都重新计算,r_t 恒等于 1,裁剪永远不起作用。
- 优势没有归一化:在每个小批量内把优势减去均值、除以标准差,训练会稳定很多。论文正文没有强调,但主流实现几乎都这样做。
- 只调 ε 不看轮数:ε 越大、训练轮数越多,新策略偏离旧策略越远。用裁剪比例曲线监控:比例持续上升时,减小学习率或轮数。
- 只在 CartPole 上下结论:CartPole 太简单,几乎任何算法都能解决。比较 PPO 和普通策略梯度时,换 LunarLander,并多跑几个随机种子。
延伸阅读
- 原论文:Proximal Policy Optimization Algorithms
- 原仓库第 29 天目录:29_PPO/ —— 代码、笔记本、练习与答案(英文)
- Spinning Up:Proximal Policy Optimization —— OpenAI 教学文档,含伪代码
- The 37 Implementation Details of Proximal Policy Optimization —— 逐条复现 PPO 的实现细节
- High-Dimensional Continuous Control Using Generalized Advantage Estimation —— PPO 使用的 GAE 原始论文