0%

【RL硬核笔记】从 Policy Gradient 到 PPO 的完整推导(修订版)

第一部分:痛点驱动的 Policy Gradient (PG) 推导

1. 强化学习的起点

我们将强化学习建模为一个随机过程。
轨迹 (Trajectory) 定义为

  • 策略 (Policy): $\pi_\theta(a|s)$
  • 轨迹分布:

其中 $\rho(s1)$ 是初始状态分布,$P(s{t+1}|s_t,a_t)$ 是环境转移概率。

目标函数 (Optimization Objective)

最常见的写法是最大化折扣累计回报:

为避免符号干扰,下面有时会省略 $\gamma$,但不影响核心推导。

❗ 痛点 1:不能直接对奖励求导

奖励来自环境交互,环境通常是黑箱;而且期望又定义在依赖于 $\theta$ 的轨迹分布上,因此不能像监督学习那样直接把梯度穿过环境。


2. Log-Derivative Trick(REINFORCE)

从定义出发:

其中 $R(\tau)$ 表示整条轨迹的累计回报。

对参数求导:

利用恒等式

得到

再展开 $\log p_\theta(\tau)$:

由于环境转移概率 $P(s_{t+1}|s_t,a_t)$ 与策略参数 $\theta$ 无关,因此

代回得

这就是最基础的 REINFORCE 形式。

直观解释:
如果某条轨迹总回报高,就提高这条轨迹中所有动作的概率;如果回报低,就降低这些动作的概率。

❗ 痛点 2:高方差

每个时间步都乘上整条轨迹的总回报,这会把大量与当前动作无关的噪声也一起灌进梯度里。


3. 改进一:因果性(Causality)与 Reward-to-Go

REINFORCE 的一个关键问题在于:动作 $a_t$ 不应该为过去的奖励负责。

形式化地说,对于当前时间步 $t$,过去的奖励 $r1,\dots,r{t-1}$ 不会受到当前动作 $a_t$ 的影响。因此在期望意义下,过去奖励对应的项会消失,留下的只需要是从当前时刻开始的未来回报:

于是梯度可改写为

这一步常被称为 reward-to-go,它不改变期望梯度,但显著降低了方差。

直观解释:
在时间步 $t$ 采取的动作,只该根据它对未来回报的影响来被奖励或惩罚,而不该背锅过去已经发生的事。


4. 改进二:Baseline 与 Advantage

虽然 reward-to-go 已经降低了方差,但它仍然会遇到一个问题:
即使当前动作只是“平均水平”,只要该状态本身未来回报大,梯度也可能把这个动作无差别地推高。

这时我们引入一个只依赖状态、与动作无关的 baseline:$b(s_t)$。

关键性质是:

证明非常直接:

因此我们可以在不改变期望梯度的前提下,把 $G_t$ 替换为 $G_t-b(s_t)$。

最常用的选择是令 baseline 近似状态价值函数:

定义优势函数(Advantage):

在采样估计里,常用

于是我们得到更实用的 PG 形式:

本质含义:
不是问“这个状态未来回报高不高”,而是问“这个动作是否比这个状态下的平均动作更好”。


5. 从 Trajectory 形式到 State-Action 形式(Policy Gradient Theorem)

从 REINFORCE 出发:

利用期望的线性性,将 trajectory 按时间步拆开:

对每一项使用条件期望(固定 (s_t, a_t)):

注意到:

因此:

最后,将对时间步的求和吸收到状态访问分布中(定义 ($d^{\pi_\theta}(s)$) 为在策略下访问 state 的频率):

得到:


第二部分:从 REINFORCE 到 Actor-Critic,再到基于旧策略样本的目标

到这里为止,主线还是标准的 on-policy policy gradient。接下来的核心问题是:

每次策略一更新,旧数据就和新策略不再完全匹配;如果每次都只用最新样本做一步更新,样本利用率会很低。

这里需要特别澄清一件事:

PPO 不是传统意义上的 fully off-policy 方法。

它的本质仍然是 on-policy / near-on-policy

  • 数据由旧策略 $\pi{\theta{\text{old}}}$ 采样;
  • 然后固定这批数据,对当前策略做若干轮优化;
  • 为了让“用旧策略采样的数据优化新策略”这件事在数学上成立,我们需要引入一个基于新旧策略比值的 surrogate objective。

因此,下面这部分不是在把 PPO 推成一个一般意义上的 off-policy 算法,而是在解释:

为什么 PPO 会自然出现 likelihood ratio,以及为什么需要限制新旧策略不要偏得太远。


1. Policy Gradient Theorem 的视角

上面从轨迹概率出发得到的是 REINFORCE 形式。更进一步,我们可以把梯度写成状态-动作分布上的形式:

其中 $d^{\pi\theta}(s)$ 表示策略 $\pi\theta$ 诱导的状态访问分布。

再减去任意只依赖状态的 baseline,可以写成

这就是从 REINFORCE 过渡到 actor-critic 的标准形式。


2. 用旧策略样本构造可优化目标

设旧策略为

我们用它采样得到一批数据 $(st,a_t,r_t)$。现在想优化一个新策略 $\pi\theta$。

对于任意固定的状态动作对 $(s_t,a_t)$,定义概率比值:

那么,对旧策略样本上的一个自然 surrogate objective 是:

其中

这个目标非常重要,因为它满足两个关键性质:

  1. 当 $\theta=\theta_{\text{old}}$ 时,$\rho_t(\theta)=1$;
  2. 在 $\theta=\theta_{\text{old}}$ 附近,它的梯度与真实目标 $J(\theta)$ 的梯度一致。

因此,它是一个一阶正确(first-order correct)的局部 surrogate objective

这正是 TRPO / PPO 的起点。


3. 为什么这里会出现 likelihood ratio?

如果直接在旧策略样本上写

那它与当前策略 $\pi_\theta$ 无关,根本无法优化。

而如果我们想在旧数据上评估“当前策略对这些动作的偏好是否应该增大或减小”,就必须把当前策略和旧策略在同一样本上的概率联系起来。最自然的量正是

它的含义非常直观:

  • 若 $\rho_t(\theta)>1$,说明新策略更倾向于这个动作;
  • 若 $\rho_t(\theta)<1$,说明新策略更不倾向于这个动作。

再乘上优势 $\hat A_t$,就得到“应该把这个动作的概率往哪个方向调”的局部优化信号。


4. 关于 trajectory-level importance sampling 的正确位置

很多讲法会先写出全轨迹 importance sampling:

再把轨迹比值展开成

这个公式本身是正确的,因为环境转移概率会在比值中消掉。

但它更适合作为直觉背景,而不适合作为 PPO 的主推导。原因在于:

  1. 全轨迹连乘的方差极大;
  2. PPO 实际优化的并不是这个 trajectory-level 目标;
  3. 更标准的路线是直接从 policy gradient theorem 与局部 surrogate objective 出发。

所以,在理解 PPO 时,trajectory-level importance sampling 可以作为“为什么 ratio 会出现”的背景说明,但不应把它当成 PPO clip 目标的正式来源。


第三部分:从 Surrogate Objective 到 TRPO / PPO 的核心思想

到这里,已经有了一个局部正确的目标:

它解决了“如何在旧策略样本上优化当前策略”的问题,但新的问题马上出现:

如果新策略和旧策略相差太大,这个局部近似就会失效。

这才是 TRPO 与 PPO 真正要解决的核心难点。


1. 为什么不能直接最大化这个目标?

看单个时间步上的项:

如果 $\hat A_t>0$,最大化它会推动 $\rho_t(\theta)$ 尽可能变大,也就是大幅提高该动作概率;
如果 $\hat A_t<0$,则会推动 $\rho_t(\theta)$ 尽可能变小,也就是大幅降低该动作概率。

问题在于:
这个目标本身并没有限制“改多大”。一旦 $\pi\theta$ 相对 $\pi{\text{old}}$ 偏移过大,

  • 旧样本对新策略不再有代表性;
  • surrogate objective 与真实目标之间的一阶近似关系会迅速变差;
  • 训练会变得不稳定,甚至崩掉。

因此,真正的问题不在于有没有 surrogate,而在于:

如何让每次更新都保持“足够近端(proximal)”。


2. TRPO 的思路:显式限制 KL 距离

TRPO 的做法是:

在最大化 surrogate objective 的同时,显式约束新旧策略之间的 KL 距离不要太大:

它的思想非常清楚:

  • surrogate objective 告诉我们“朝哪里改”;
  • KL 约束告诉我们“每次别改太远”。

TRPO 具有很强的理论动机,但工程实现较复杂,因为它通常涉及二阶近似、共轭梯度等操作。


3. PPO 的思路:用更简单的方式近似“近端更新”

PPO 的目标不是推翻 TRPO,而是用更简单、更稳定、更适合深度学习训练的方式,近似实现“不要偏离太远”这一思想。

PPO 最常见的版本是 PPO-Clip

它并不显式加一个硬 KL 约束,而是直接在每个样本的 ratio 上做截断:

定义裁剪函数:

然后构造目标:

这就是 PPO 的核心公式。


第四部分:为什么 PPO-Clip 这样设计是合理的?

1. 先看不裁剪时会发生什么

如果只有

那优化器会想办法把对目标有利的 $\rho_t$ 推得越来越极端:

  • 对于 $\hat A_t>0$ 的样本,希望 $\rho_t$ 越大越好;
  • 对于 $\hat A_t<0$ 的样本,希望 $\rho_t$ 越小越好。

这会使策略更新缺乏约束,导致 surrogate 失真。


2. 对正优势样本的解释

若 $\hat A_t>0$,则我们希望提高该动作概率,也就是希望 $\rho_t(\theta)$ 变大。

此时:

当 $\rho_t \le 1+\epsilon$ 时,裁剪不起作用;
当 $\rho_t > 1+\epsilon$ 时,第二项变成 $(1+\epsilon)\hat A_t$,而它比第一项更小,因此 min 会选择被裁剪后的那一项。

含义:
这个动作是好的,可以提高它的概率;但一旦提高幅度超过阈值,就不再继续鼓励。


3. 对负优势样本的解释

若 $\hat A_t<0$,则我们希望降低该动作概率,也就是希望 $\rho_t(\theta)$ 变小。

当 $\rho_t < 1-\epsilon$ 时,裁剪后的比值变成 $1-\epsilon$。因为此时乘的是一个负数,

所以 min 会选更小的那个,也就是裁剪后的项。

含义:
这个动作是坏的,可以降低它的概率;但一旦降得过猛,也不再继续鼓励。


4. min 的真正作用

min 并不是在构造一个对真实目标的严格数学下界,而是在构造一个更保守的 surrogate objective

它的效果是:

  • 当策略更新还在合理区间内时,目标基本等同于原始 surrogate;
  • 当更新试图把 ratio 推得过大或过小时,目标会自动变“保守”,抑制继续朝极端方向走。

因此,PPO-Clip 的核心不是“精确逼近 TRPO 的 KL 约束”,而是用一种非常简单的样本级机制,达到“近端更新”的效果。


第五部分:Advantage 的实际估计 —— 为什么 PPO 通常配合 GAE

到目前为止,公式里一直写的是 $\hat A_t$。但在实际算法里,优势函数并不是直接已知的,需要估计。

最简单的估计是 Monte Carlo:

但它仍然可能方差较大,因此 PPO 中更常见的是 GAE (Generalized Advantage Estimation)

先定义 TD residual:

然后定义 GAE:

它可以看作在 bias 与 variance 之间做折中:

  • $\lambda$ 大,接近 Monte Carlo,偏差更小但方差更大;
  • $\lambda$ 小,接近 TD,方差更小但偏差更大。

在工程实践中,PPO 几乎总会和 GAE 搭配使用。


第六部分:PPO 的完整训练目标

PPO 通常采用 actor-critic 架构,因此除了策略目标之外,还会同时训练价值函数,并加上熵正则以鼓励探索。

若将 actor 参数记为 $\theta$,critic 参数记为 $\phi$,则一个常见的总目标写作:

其中:

  • $L^{\text{CLIP}}_t(\theta)$ 是前面定义的 clipped surrogate;
  • $V_t^{\text{target}}$ 是 value regression 的监督信号,常由回报或 bootstrap target 构造;
  • $\mathcal H(\pi_\theta(\cdot|s_t))$ 是策略熵,用来鼓励探索;
  • $c_1,c_2$ 是权重系数。

如果 actor 与 critic 共享部分网络参数,上式也常被合并写成单个参数 $\theta$ 的形式;但从概念上区分 $\theta$ 与 $\phi$ 会更清晰。


第七部分:把公式串成算法流程

到这里,PPO 的推导已经闭环了。它的实际训练流程可以概括为:

  1. 用当前策略 $\pi_{\text{old}}$ 与环境交互,采样一批轨迹;
  2. 用 critic 计算每个状态的 $V(s_t)$;
  3. 根据奖励和价值函数,计算 $\hat A_t$(通常用 GAE)以及 value target;
  4. 固定这批由旧策略采样的数据,做若干个 epoch 的 mini-batch SGD;
  5. 优化的 actor 目标是 clipped surrogate objective;
  6. 同时优化 critic loss 与 entropy bonus;
  7. 更新完成后,把当前策略记作新的 $\pi_{\text{old}}$,进入下一轮采样。

这也解释了为什么 PPO 通常被称为 on-policy / near-on-policy
它虽然会对同一批旧数据重复优化多轮,但这些数据仍然只来自最近一轮旧策略,而不是像 DQN/SAC 那样在长期 replay buffer 中反复混用来自很多历史策略的数据。


总结

从 Policy Gradient 到 PPO 的演进,本质上是一条不断解决“高方差”和“更新不稳定”问题的路线:

  1. REINFORCE:
    用 log-derivative trick 绕开环境不可导,但梯度方差很大。

  2. Reward-to-Go + Baseline/Advantage:
    利用因果性去掉过去奖励的噪声,再通过 baseline 判断动作是否“优于平均”,进一步降低方差。

  3. Policy Gradient Theorem + Actor-Critic:
    把轨迹级视角转成状态-动作级视角,得到更适合实际训练的优势函数形式。

  4. Old-policy surrogate objective:
    为了在旧策略采样的数据上优化当前策略,引入 likelihood ratio

    构造局部正确的 surrogate objective

  5. TRPO / PPO:
    当新旧策略偏得太远时,surrogate 会失效;TRPO 用 KL 约束显式限制步长,PPO 用 clipping 给出更简单、更稳定的近端更新机制。

所以,PPO 的本质并不是“把 off-policy importance sampling 做得更稳定”,而是:在基于旧策略样本的局部 surrogate objective 上,通过限制新旧策略偏离,稳定地进行策略优化。

这才是从 Policy Gradient 到 PPO 最核心的那条逻辑主线。