RL ML Learning Lab
10 / 12
策略优化 · 信任区域

PPOProximal Policy Optimization

第 9 章的 AC 每步更新,但更新幅度完全不受控——一步过头就可能毁掉整个策略。本章的 PPO 用「裁剪目标」把每次更新锁在信任区域内:简单、稳定、可大规模并行,是 OpenAI 训练 ChatGPT 的 RLHF 底座。

2.5h
阅读 + 实操
2 个
交互演示
进阶
难度

裁剪目标 · 机制可视化

优势 A+1.0
ε0.20
信任区域[0.80, 1.20]
优势 A 1.00
裁剪 ε 0.20

实线 = 有效目标 min(r·A, clip(r)·A)。虚线 = 未裁剪的 r·A。信任区域之外目标变平 → 梯度为 0 → 策略不会被推得太远。

PPO vs A2C vs DQN · CartPole 同场对比

Ep0
步数0
最佳0

当前观看:PPO 的 CartPole

三个算法(PPO / A2C / DQN)独立训练。PPO 按批收集后统一更新,A2C 每步 TD 更新,DQN 经验回放更新——比谁的曲线爬得快、站得稳。

三个算法独立训练,比较的是各自收敛速度与稳定性,不是共享参数的接力训练。

学习率 0.005
γ 折扣 0.99
速度 20 步/秒

为什么学这步?

策略梯度方法普遍脆弱:更新步长稍大,策略一步崩溃;稍小,训练慢如蜗牛。PPO 用「裁剪」代替二阶信任区域优化(TRPO),在几乎零调参成本下获得稳定的更新——因此成为 OpenAI 训练 ChatGPT 与 Claude 等大模型 RLHF 阶段的事实标准。它是现代 RL 的「工业底座」。

下一步预告:PPO 能对齐"奖励"本身。下一章 RLHF 把人类偏好变成奖励模型,用 PPO 教会大模型"说人类爱听的话"。

📌 发生了什么

  • 重要性采样比率 r = π_new/π_old,让一批旧数据可被多次更新
  • 裁剪目标把单次更新限制在 [1−ε, 1+ε] 的信任区域内
  • GAE(γ, λ) 在偏差与方差之间滑动权衡优势估计
  • CartPole 上 PPO 的曲线比无约束的 A2C 更稳

⚠️ 常见陷阱

  • 误以为 ε 越大越好——ε 太大信任区域名存实亡,退化为无约束策略梯度
  • 多轮 epoch 里更新 ratio 的分母——π_old 必须冻结为收集数据时的策略
  • 忽略 λ 的作用——λ 控制 GAE 的偏差-方差权衡,不是可以随便设的常数

本章小结

  • PPO = 收集轨迹 + GAE 优势 + 裁剪目标多轮更新
  • 裁剪让每次更新的「步长」被限制,稳定性远超无约束方法
  • 简单、稳健、可并行 → 大模型 RLHF 的事实标准

📐 PPO 推导:从策略梯度到裁剪目标

策略梯度 J(θ) = E[∇logπ_θ(a|s)·A]。若想用旧策略 π_old 收集的数据训练新策略 π_θ,需要重要性采样修正:每一项乘上比率 r(θ)。

直接最大化 r·A 有风险:若 r 变得很大(新策略远偏离旧策略),一次更新就可能摧毁策略。TRPO 用约束保证「安全距离」,但实现复杂;PPO 换了个思路——把目标本身钳制住。

min 的妙处:当 r 越过信任区域边界时,取到的是常数 clip(r)·A,梯度为 0——策略「不前进也不后退」,在原地等待数据更新。A>0 时只剪 r 的上界(防止过度推崇好动作),A<0 时只剪下界。

GAE(γ, λ) 把多步 TD 误差按 (γλ)^l 加权求和:λ=0 是一步 TD(低方差高偏差),λ=1 是 MC 回报(无偏差高方差),0<λ<1 在两者间插值——PPO 通常取 λ≈0.95。

🎛 PPO 超参对比

PPO 以「几乎不用调参」著称,但少数几个旋钮仍直接影响稳定性。

超参 表现 结果
ε 过大(> 0.5) 信任区域几乎不设限 退化为 A2C
ε ≈ 0.1 ~ 0.3 更新受限但仍能快速学习 推荐
epochs 过多(> 10) 同一批数据反复拟合 过拟合旧批
λ ≈ 0.95 偏差-方差平衡良好 默认推荐

💡 经验法则:ε=0.2、λ=0.95、epochs=3 是几乎处处可用的起点;若 clipFrac 长期接近 100%,先调小学习率而不是调大 ε。

💻 PPO 核心循环

「收集 → 算优势 → 裁剪更新」三步循环,伪代码即实现。

for iteration in range(T):
    # 1) 用当前策略收集一批轨迹,记录旧 log 概率
    for (s, a, r, done) in rollout():
        old_logp.append(log_prob(policy, s, a))
    # 2) GAE 计算优势与回报
    A = gae(rewards, values, gamma, lam)
    G = discounted_returns(rewards, gamma)
    # 3) 多轮 epoch:裁剪目标更新策略,MSE 更新价值
    for epoch in range(K):
        for (s, a, adv, g, old) in batch():
            ratio = exp(log_prob(policy, s, a) - old)   # π_new/π_old
            clipped = clamp(ratio, 1-eps, 1+eps)
            loss = -min(ratio*adv, clipped*adv)         # 裁剪目标
            policy_step(loss)
            value_step(mse(V(s), g))

📚 参考文献与延伸阅读

  1. Schulman, J. et al. (2017), Proximal Policy Optimization Algorithms, arXiv:1707.06347 — PPO 原始论文,裁剪目标的定义与对比实验
  2. Schulman, J. et al. (2016), High-Dimensional Continuous Control Using Generalized Advantage Estimation, ICLR — GAE 原始论文
  3. Schulman, J. et al. (2015), Trust Region Policy Optimization, ICML — TRPO,PPO 的信任区域思想来源
  4. OpenAI Spinning Up: PPO — 最小可读实现与直觉讲解

📝 课后练习

检验你的理解——答对为止