PPO算法原理详解(下)
-
- 前言
- 一、PPO-Clip:裁剪目标函数的原理
-
- [1.1 从代理损失函数说起](#1.1 从代理损失函数说起)
- [1.2 Clip裁剪机制的核心思想](#1.2 Clip裁剪机制的核心思想)
- [1.3 为什么这样裁剪?------分情况讨论](#1.3 为什么这样裁剪?——分情况讨论)
- [1.4 裁剪机制的直观理解](#1.4 裁剪机制的直观理解)
- 二、PPO-Penalty:带惩罚的版本
- 三、GAE:广义优势估计
-
- [3.1 为什么需要GAE?](#3.1 为什么需要GAE?)
- [3.2 GAE的公式](#3.2 GAE的公式)
- 四、PPO完整算法流程
-
- [4.1 PPO算法伪代码](#4.1 PPO算法伪代码)
- [4.2 PPO的关键特点](#4.2 PPO的关键特点)
- 五、实践中的调参技巧
-
- [5.1 关键超参数](#5.1 关键超参数)
- [5.2 常见问题与解决方法](#5.2 常见问题与解决方法)
- [5.3 归一化技巧](#5.3 归一化技巧)
- 六、PPO的优缺点与应用场景
-
- [6.1 优点](#6.1 优点)
- [6.2 缺点](#6.2 缺点)
- [6.3 典型应用场景](#6.3 典型应用场景)
- 总结
前言
在上一篇文章中,我们从策略梯度的基本原理出发,回顾了从REINFORCE到TRPO的演进历程,理解了PPO算法为什么会被提出------它是为了在保持TRPO稳定性的同时,大幅简化算法实现。
本篇我们将深入PPO的核心机制,详细讲解Clip裁剪目标函数的原理、GAE广义优势估计、PPO完整伪代码,以及实际训练中的调参技巧。
一、PPO-Clip:裁剪目标函数的原理
1.1 从代理损失函数说起
上一篇我们提到,PPO使用概率比 r t ( θ ) = π θ ( a t ∣ s t ) π θ o l d ( a t ∣ s t ) r_t(\theta) = \frac{\pi_\theta(a_t|s_t)}{\pi_{\theta_{old}}(a_t|s_t)} rt(θ)=πθold(at∣st)πθ(at∣st) 来衡量新旧策略的差异。
PPO的原始代理目标函数(也就是未加裁剪的版本)是:
L C P I ( θ ) = E ^ t r t ( θ ) A \^ t L_{CPI}(\theta) = \hat{E}_t \left r_t(\\theta) \\hat{A}_t \\right LCPI(θ)=E^trt(θ)A\^t
其中 A ^ t \hat{A}_t A^t 是优势函数的估计值。
这个目标函数的问题我们在上一篇已经分析过了:不加约束地最大化它,会导致策略更新幅度过大。
1.2 Clip裁剪机制的核心思想
PPO的解决方案非常巧妙------直接把概率比 r t ( θ ) r_t(\theta) rt(θ) 裁剪在 1 − ϵ , 1 + ϵ 1-\\epsilon, 1+\\epsilon 1−ϵ,1+ϵ 范围内,然后取裁剪前后两者的较小值作为目标。
最终的PPO-Clip目标函数是:
L C L I P ( θ ) = E ^ t min ( r t ( θ ) A \^ t , clip ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) A \^ t ) L^{CLIP}(\theta) = \hat{E}_t \left \\min \\left( r_t(\\theta) \\hat{A}_t, \\; \\text{clip}(r_t(\\theta), 1-\\epsilon, 1+\\epsilon) \\hat{A}_t \\right) \\right LCLIP(θ)=E^tmin(rt(θ)A\^t,clip(rt(θ),1−ϵ,1+ϵ)A\^t)
其中 ϵ \epsilon ϵ 是一个超参数,通常取0.1或0.2。
1.3 为什么这样裁剪?------分情况讨论
让我们分两种情况来理解这个裁剪函数的作用:
情况一:优势函数 A ^ t > 0 \hat{A}_t > 0 A^t>0(这个动作比平均好)
我们希望增大这个动作的概率,也就是让 r t ( θ ) r_t(\theta) rt(θ) 变大。
- 当 r t ( θ ) < 1 + ϵ r_t(\theta) < 1+\epsilon rt(θ)<1+ϵ 时:目标就是 r t ( θ ) ⋅ A ^ t r_t(\theta) \cdot \hat{A}_t rt(θ)⋅A^t,正常上升
- 当 r t ( θ ) > 1 + ϵ r_t(\theta) > 1+\epsilon rt(θ)>1+ϵ 时:裁剪后的值是 ( 1 + ϵ ) ⋅ A ^ t (1+\epsilon) \cdot \hat{A}_t (1+ϵ)⋅A^t,目标不再增加
这意味着: 当我们已经把这个好动作的概率提高了足够多(超过了 1 + ϵ 1+\epsilon 1+ϵ 倍),再继续提高就没有额外收益了,梯度变为0。
情况二:优势函数 A ^ t < 0 \hat{A}_t < 0 A^t<0(这个动作比平均差)
我们希望减小这个动作的概率,也就是让 r t ( θ ) r_t(\theta) rt(θ) 变小。
- 当 r t ( θ ) > 1 − ϵ r_t(\theta) > 1-\epsilon rt(θ)>1−ϵ 时:目标就是 r t ( θ ) ⋅ A ^ t r_t(\theta) \cdot \hat{A}_t rt(θ)⋅A^t,因为 A ^ t \hat{A}_t A^t 是负数, r t r_t rt 越小,目标越大
- 当 r t ( θ ) < 1 − ϵ r_t(\theta) < 1-\epsilon rt(θ)<1−ϵ 时:裁剪后的值是 ( 1 − ϵ ) ⋅ A ^ t (1-\epsilon) \cdot \hat{A}_t (1−ϵ)⋅A^t,目标不再变化
这意味着: 当我们已经把这个差动作的概率降低了足够多(低于 1 − ϵ 1-\epsilon 1−ϵ 倍),再继续降低也没有额外收益了,梯度变为0。
1.4 裁剪机制的直观理解
我们可以用一个表格来总结裁剪机制的效果:
| 优势函数符号 | 概率比范围 | 目标函数值 | 效果 |
|---|---|---|---|
| A t > 0 A_t > 0 At>0 | r < 1 + ϵ r < 1+\epsilon r<1+ϵ | r ⋅ A t r \cdot A_t r⋅At(随r增大) | 鼓励增大好动作概率 |
| A t > 0 A_t > 0 At>0 | r > 1 + ϵ r > 1+\epsilon r>1+ϵ | ( 1 + ϵ ) ⋅ A t (1+\epsilon) \cdot A_t (1+ϵ)⋅At(常数) | 不再继续增大 |
| A t < 0 A_t < 0 At<0 | r > 1 − ϵ r > 1-\epsilon r>1−ϵ | r ⋅ A t r \cdot A_t r⋅At(随r减小而增大) | 鼓励减小差动作概率 |
| A t < 0 A_t < 0 At<0 | r < 1 − ϵ r < 1-\epsilon r<1−ϵ | ( 1 − ϵ ) ⋅ A t (1-\epsilon) \cdot A_t (1−ϵ)⋅At(常数) | 不再继续减小 |
这种设计的精妙之处在于:它直接从目标函数层面阻止了策略更新超出信赖域的范围,不需要复杂的约束优化,只需要一次普通的梯度下降就能实现。
二、PPO-Penalty:带惩罚的版本
除了PPO-Clip,原始论文中还提出了另一种变体------PPO-Penalty(带KL惩罚的目标函数):
L K L P E N ( θ ) = E ^ t r t ( θ ) A \^ t − β ⋅ K L ( π θ o l d ( ⋅ ∣ s t ) ∥ π θ ( ⋅ ∣ s t ) ) L^{KLPEN}(\theta) = \hat{E}_t \left r_t(\\theta) \\hat{A}_t - \\beta \\cdot KL\\left( \\pi_{\\theta_{old}}(\\cdot\|s_t) \\parallel \\pi_\\theta(\\cdot\|s_t) \\right) \\right LKLPEN(θ)=E^trt(θ)A\^t−β⋅KL(πθold(⋅∣st)∥πθ(⋅∣st))
这个版本的思路是:不硬裁剪,而是在目标函数里加上一个KL散度的惩罚项 β ⋅ K L \beta \cdot KL β⋅KL。
- 如果新旧策略差异太大(KL散度大),就会被惩罚
- β \beta β 是自适应调整的:如果实际KL散度超过目标值,就增大 β \beta β;如果太小,就减小 β \beta β
PPO-Clip vs PPO-Penalty:
- 实践中,PPO-Clip效果更好、更常用,也是默认选择
- PPO-Penalty更接近TRPO的思想,但实现仍然比TRPO简单
- 大多数开源实现(如OpenAI Baselines、Stable Baselines3)都使用PPO-Clip
三、GAE:广义优势估计
3.1 为什么需要GAE?
在实际训练中,优势函数 A t A_t At 的估计质量直接影响训练效果。我们有几种估计方式:
-
单步估计 : A t = r t + γ V ( s t + 1 ) − V ( s t ) A_t = r_t + \gamma V(s_{t+1}) - V(s_t) At=rt+γV(st+1)−V(st)
- 优点:偏差小
- 缺点:方差大
-
蒙特卡洛估计 : A t = ∑ k = t T γ k − t r k − V ( s t ) A_t = \sum_{k=t}^{T} \gamma^{k-t} r_k - V(s_t) At=∑k=tTγk−trk−V(st)
- 优点:方差小
- 缺点:偏差大
能不能在偏差和方差之间找一个平衡点?这就是**GAE(Generalized Advantage Estimation,广义优势估计)**的作用。
3.2 GAE的公式
GAE引入了一个参数 λ \lambda λ(通常取0.95),通过指数加权的方式综合不同步长的优势估计:
A ^ t G A E ( γ , λ ) = ∑ l = 0 ∞ ( γ λ ) l δ t + l \hat{A}t^{GAE(\gamma, \lambda)} = \sum{l=0}^{\infty} (\gamma \lambda)^l \delta_{t+l} A^tGAE(γ,λ)=l=0∑∞(γλ)lδt+l
其中 δ t = r t + γ V ( s t + 1 ) − V ( s t ) \delta_t = r_t + \gamma V(s_{t+1}) - V(s_t) δt=rt+γV(st+1)−V(st) 是单步时序差分误差。
参数的作用:
- λ = 0 \lambda = 0 λ=0:退化为单步估计(高方差,低偏差)
- λ = 1 \lambda = 1 λ=1:退化为蒙特卡洛估计(低方差,高偏差)
- 通常取 λ = 0.95 \lambda = 0.95 λ=0.95,在两者之间取得很好的平衡
GAE是PPO实践中非常重要的组成部分,几乎所有PPO实现都会用到它。
四、PPO完整算法流程
4.1 PPO算法伪代码
初始化策略网络 π_θ 和价值网络 V_φ
for 轮次 = 1, 2, ..., N:
# 第一步:用当前策略采样数据
用 π_θ_old 采样 T 步轨迹,得到 (s_1, a_1, r_1, ..., s_T)
# 第二步:计算优势和回报
计算每个时刻的回报 R_t
用 GAE 计算优势估计 A_t
# 第三步:多轮更新策略(这是PPO的关键!)
for 每一轮更新 = 1, 2, ..., K:
# 计算概率比
r_t(θ) = π_θ(a_t|s_t) / π_θ_old(a_t|s_t)
# 计算CLIP目标函数
L_clip = min(r_t * A_t, clip(r_t, 1-ε, 1+ε) * A_t)
# 更新策略网络
θ ← θ + α ∇_θ L_clip
# 更新价值网络
φ ← φ - α ∇_φ (V_φ(s_t) - R_t)^2
# 更新旧策略
π_θ_old ← π_θ
4.2 PPO的关键特点
-
采样一次,更新多次:这是PPO效率高的关键。传统的策略梯度方法采样一次只能更新一次,而PPO可以用同一批数据更新K次(通常是3-15次),大大提高了样本利用率。
-
Actor-Critic架构:同时训练策略网络(Actor)和价值网络(Critic)。
-
共享网络backbone:通常策略网络和价值网络共享前面的几层特征提取层,最后分开输出。
五、实践中的调参技巧
5.1 关键超参数
| 超参数 | 常用值 | 说明 |
|---|---|---|
| ϵ \epsilon ϵ (clip范围) | 0.1 ~ 0.2 | 策略更新的最大幅度 |
| γ \gamma γ (折扣因子) | 0.99 | 未来回报的折扣 |
| λ \lambda λ (GAE参数) | 0.95 | 优势估计的偏差方差权衡 |
| 学习率 α \alpha α | 3e-4 | 策略网络和价值网络的学习率 |
| batch size | 64 ~ 2048 | 每次更新的样本数 |
| 更新轮数 K | 3 ~ 10 | 同一批数据重复使用的次数 |
| 熵系数 | 0.01 | 鼓励探索的熵奖励权重 |
5.2 常见问题与解决方法
问题1:训练不收敛,奖励波动大
- 降低学习率
- 增大batch size
- 减小 ϵ \epsilon ϵ
- 检查优势函数是否归一化
问题2:策略过早收敛到局部最优
- 增大熵系数(entropy coefficient)
- 增加探索噪声
- 调整网络结构
问题3:价值网络估计不准
- 单独调高价值网络的学习率
- 增加价值网络的容量
- 检查回报是否归一化
5.3 归一化技巧
实践中非常重要但容易被忽略的技巧:
- 优势归一化 :把同一批数据的优势 A t A_t At 归一化为均值0、方差1
- 回报归一化 :把回报 R t R_t Rt 归一化
- 观察值归一化:对状态输入做标准化
这些归一化操作能大幅提升训练稳定性。
六、PPO的优缺点与应用场景
6.1 优点
- 实现简单:相比TRPO,PPO的代码量少了一个数量级
- 训练稳定:Clip机制保证了策略更新不会太激进
- 样本效率高:同一批数据可以多轮更新
- 适用范围广:连续动作空间、离散动作空间都能用
6.2 缺点
- 仍然是on-policy算法:虽然比纯on-policy好,但样本效率还是不如off-policy算法(如DDPG、SAC)
- 对超参数敏感:不同任务需要调不同的参数
- 高维样本效率低:在大规模问题上,样本效率仍然是瓶颈
6.3 典型应用场景
- 游戏AI:Atari游戏、MuJoCo控制、星际争霸AI(AlphaStar)
- 机器人控制:机械臂操作、 locomotion运动控制
- 大语言模型对齐:RLHF(基于人类反馈的强化学习),ChatGPT的核心算法之一就是PPO
- 推荐系统:动态推荐策略优化
总结
PPO算法之所以能成为深度强化学习最主流的算法,核心在于它在效果、复杂度、稳定性三者之间取得了极佳的平衡:
- 它有TRPO级别的训练稳定性
- 但实现却像普通的策略梯度一样简单
- 样本效率也足够优秀
从最初的游戏AI,到如今大语言模型的对齐训练,PPO已经成为了强化学习领域的"瑞士军刀"------不是最先进的,但一定是最实用、最可靠的。
参考资料:
- John Schulman et al. "Proximal Policy Optimization Algorithms". 2017.
- John Schulman et al. "High-Dimensional Continuous Control Using Generalized Advantage Estimation". 2016.
- OpenAI Spinning Up 官方教程