跳转至

7 近端策略优化

3 时序差分算法 中,我们谈到过在线/离线策略算法,在《Easy RL:强化学习教程》一书中,这两种训练方法被称为同策略/异策略。如果要学习的智能体和与环境交互的智能体是相同的,就是同策略;反之,就是异策略。

策略梯度算法是一种同策略的算法,大多数时间都在采样数据,采样到一条完整轨迹之后才能更新策略一次,这样效率太低,不好。

重要性采样

\(x\) 服从分布 \(p\) 时,若要估计 \(f(x)\) 期望值,可从分布 \(p\) 中采样一些数据 \(x_i\) ,并计算 \(f(x_i)\) 的平均值,以近似该期望值:

\[\mathbb{E}_{x\sim p}[f(x)]\approx \frac{1}{N}\sum_{i=1}^{N}f(x_i)\]

现在的问题是,有没有办法不从分布 \(p\) 中采样,而是从另一个分布 \(q\) 中采样数据,并通过采样所得数据估计 \(x\) 服从分布 \(p\) 时的 \(f(x)\) 期望值?

由于 \(\mathbb{E}_{x\sim p}[f(x)] = \int f(x)p(x) \mathrm{d}x\) ,所以可以通过如下变换解决该问题

\[\mathbb{E}_{x\sim p}[f(x)]=\int f(x)p(x)\mathrm{d}x = \int f(x)\frac{p(x)}{q(x)}q(x)\mathrm{d}x = \mathbb{E}_{x\sim q}\left[f(x)\frac{p(x)}{q(x)}\right]\approx\frac{1}{N}\sum_{i=1}^{N}f(x_i)\frac{p(x_i)}{q(x_i)}\]

也就是说,我们从另一个分布 \(q\) 中采样数据 \(x\) ,计算 \(f(x)\dfrac{p(x)}{q(x)}\) 再取期望,即得 \(x\) 服从分布 \(p\) 时的 \(f(x)\) 期望值。这里的 \(\dfrac{p(x)}{q(x)}\) 被称为 重要性权重 (importance weight) .

分布差距不能太大

虽然理论上,我们可以用一个任意的分布 \(q\) 来采样数据,估计 \(x\) 服从分布 \(p\) 时的 \(f(x)\) 期望值。但实际中, \(p\)\(q\) 的差距不能太大。这是为了保证其方差差距不大。

\[\begin{aligned} \mathrm{Var}_{x\sim p}[f(x)] &= \mathbb{E}_{x\sim p}[f^2(x)] - (\mathbb{E}_{x\sim p}[f(x)])^2\\ \mathrm{Var}_{x\sim q}\left[f(x)\frac{p(x)}{q(x)}\right] &= \mathbb{E}_{x\sim q}\left[\left(f(x)\frac{p(x)}{q(x)}\right)^2\right] - \left(\mathbb{E}_{x\sim q}\left[f(x)\frac{p(x)}{q(x)}\right]\right)^2\\ &= \int f^2(x)\frac{p^2(x)}{q^2(x)}q(x)\mathrm{d}x - \left(\mathbb{E}_{x\sim p}[f(x)]\right)^2\\ &= \int f^2(x)\frac{p(x)}{q(x)}p(x)\mathrm{d}x-(\mathbb{E}_{x\sim p}[f(x)])^2\\ &= \mathbb{E}_{x\sim p}\left[f^2(x)\frac{p(x)}{q(x)}\right]-(\mathbb{E}_{x\sim p}[f(x)])^2 \end{aligned}\]

可见,若 \(\dfrac{p(x)}{q(x)}\) 相差很大,则两个随机变量的方差就会相差很大。此时,虽然二者理论上的期望值相同,但是在采样次数不够多的情况下,用一者的采样均值估计另一者的期望值,可能有非常大的误差。

修改同策略训练为异策略训练

Question

Q:从同策略改为异策略有什么优势?

A:\(\theta'\) 与环境交互采样大量数据后,\(\theta\) 可以多次重复利用这些数据更新参数。一方面,数据采样和参数更新可以并行进行;另一方面,一组数据可以被重复利用。

在策略梯度算法中,策略更新过程可以表示为:

\[\theta \leftarrow \theta + \frac{\eta}{N}\sum_{n=1}^{N} \sum_{t=0}^T\left[\left(\sum_{t'=t}^T \gamma^{t'-t} r^{\{n\}}_{t'} - b\right) \nabla_\theta \log \pi_\theta\left(a^{\{n\}}_t|s^{\{n\}}_t\right)\right]\]

实际每一次更新的梯度可以表示为

\[\mathbb{E}_{(s_t,a_t)\sim\pi_\theta}\left[A^{\theta}(s_t,a_t)\nabla_{\theta}\log \pi_\theta(a_t|s_t)\right]\]

上式代表我们用策略 \(\pi_{\theta}\) 与环境进行交互采样出状态动作对 \((s_t,a_t)\),计算 \(A^{\theta}(s_t,a_t)\nabla_{\theta}\log \pi_\theta(a_t|s_t)\) .

现在,我们希望不用 \(\pi_\theta\) ,而是用一个新策略 \(\pi_{\theta'}\) 与环境交互,它的作用是给 \(\theta\) 做示范,让 \(\theta\) 利用它采样得到的数据进行梯度上升更新。 \(\pi_{\theta'}\) 采样所得状态动作对服从 \(\pi_{\theta'}\) 分布,而不是 \(\pi_\theta\) 分布,但没有关系,我们可以使用重要性采样解决这个问题。

\[\begin{aligned} &\mathbb{E}_{(s_t,a_t)\sim\pi_\theta}\left[A^{\theta}(s_t,a_t)\nabla_{\theta}\log \pi_\theta(a_t|s_t)\right]\\ =& \mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta}(s_t,a_t)\nabla_{\theta}\log\pi_{\theta}(a_t|s_t) \frac{\pi_{\theta}(s_t,a_t)}{\pi_{\theta'}(s_t,a_t)}\right]\\ =& \mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta}(s_t,a_t)\nabla_{\theta}\log\pi_{\theta}(a_t|s_t) \frac{\pi_{\theta}(a_t|s_t)p_{\theta}(s_t)}{\pi_{\theta'}(a_t|s_t)p_{\theta'}(s_t)}\right] \end{aligned}\]

Note

理论上,此处 \(A^{\theta}(s_t,a_t)\nabla_{\theta}\log\pi_{\theta}(a_t|s_t)\) 相当于重要性采样中的 \(f(x)\) ,所以不会随着分布从 \(\pi_{\theta}\) 变为 \(\pi_{\theta'}\) 而发生变化。

但实际上,由于与环境进行交互的是 \(\theta'\) ,我们无法估计出 \(A^{\theta}(s_t, a_t)\) ,只能估计出 \(A^{\theta'}(s_t,a_t)\) .

我们不管三七二十一,直接假设 \(A^{\theta'}(s_t, a_t) \approx A^{\theta}(s_t,a_t)\) .

Note

上式中的 \(p_{\theta}(s_t)\)\(p_{\theta'}(s_t)\) 在绝大多数情况下难以估计,尤其是 \(p_{\theta}(s_t)\) ,因为 \(\theta\) 都不与环境进行交互。

同样地,我们不管三七二十一,直接假设 \(p_{\theta}(s_t) \approx p_{\theta'}(s_t)\) .

从而,异策略更新的梯度可以表示为

\[\mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta’}(s_t,a_t)\nabla_{\theta}\log\pi_{\theta}(a_t|s_t) \frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right]\]

接下来,利用 \(\nabla f(x) = f(x) \nabla \log f(x)\) ,上式可进一步表示为

\[\begin{aligned} &\mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta’}(s_t,a_t)\frac{\nabla_{\theta}\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right]\\ =& \nabla_{\theta}\left\{\mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta’}(s_t,a_t)\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right]\right\} \end{aligned}\]

换言之,当我们使用重要性采样,将策略梯度算法从同策略训练改为异策略训练后,我们每次更新策略参数 \(\theta\) ,实际上是在优化目标函数

\[J^{\theta'}(\theta) = \mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta’}(s_t,a_t)\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right]\]

\(J^{\theta'}(\theta)\) 表示待优化的目标函数,括号中的 \(\theta\) 表示要优化的参数,上标 \(\theta'\) 表示与环境做交互,给 \(\theta\) 做示范的策略参数。


我们来看看这个目标函数到底表达了什么意思。

我们要优化 \(\theta\) ,使得对于满足 \(\pi_{\theta'}\) 分布的状态动作对 \((s_t,a_t)\)\(A^{\theta'}(s_t,a_t)\dfrac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\) 期望值尽可能大。

我们注意到,只有 \(\pi_{\theta}(a_t|s_t)\) 一项与要优化的参数 \(\theta\) 有关; \(A^{\theta'}(s_t,a_t)\) 表示遵循策略 \(\pi_{\theta'}\) 时,在状态 \(s_t\) 选择动作 \(a_t\) 的优势,可正可负; \(\pi_{\theta'}(a_t|s_t)\) 表示策略 \(\pi_{\theta'}\) 在状态 \(s_t\) 选择动作 \(a_t\) 的概率,取值在 [0,1] 之间。

为了使 \(A^{\theta'}(s_t,a_t)\dfrac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\) 尽可能大,当 \(A^{\theta'}(s_t,a_t)\) 为正数时,应尽可能使 \(\pi_{\theta}(a_t|s_t)\) 增大;当 \(A^{\theta'}(s_t,a_t)\) 为负数时,应尽可能使 \(\pi_{\theta}(a_t|s_t)\) 减小。

也就是说,当策略 \(\pi_{\theta'}\) 通过大量的采样数据,估计在状态 \(s_t\) 采取动作 \(a_t\) 有优势时,就增加策略 \(\pi_\theta\) 在状态 \(s_t\) 选择动作 \(a_t\) 的概率,反之减小这一概率。


近端策略优化 PPO

我们利用重要性采样,将策略梯度算法从同策略方法改为异策略方法,提升了其训练效率。在重要性采样中,我们提到,两策略的概率分布不能相差太大,否则会因方差相差过大而导致误差过大。

近端策略优化 (proximal policy optimization, PPO) 要解决的问题就是,如何避免两策略的概率分布,即 \(\pi_{\theta}(a_t|s_t)\)\(\pi_{\theta'}(a_t|s_t)\) 相差太多?


换一种视角。原始的策略梯度算法,其优化的目标函数为 \(J(\theta) = \mathbb{E}_{\tau\sim p(\tau|\theta)}[R(\tau)]\) ,更新方式为 \(\theta \leftarrow \theta + \alpha \nabla_{\theta} J(\theta)\) . 这种方法的问题是,倘若步长过长,策略可能突然显著变差,影响训练效果。但是我们一不可能就同一任务反复测试确定最优步长,二不可能将步长设定为一个极小的值——两种方法都耗时耗力,需要一个新方法能自己解决步长过长的问题。(自适应步长?)

利用重要性采样之后,优化的目标函数变为 \(J^{\theta'}(\theta) = \mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta’}(s_t,a_t)\dfrac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right]\) ,更新方式为 \(\theta \leftarrow \theta + \alpha \nabla_{\theta}J^{\theta'}(\theta)\) ,参照上文对目标函数的直观理解,我们可以认为新策略 \(\theta\) 是旧策略 \(\theta'\) 的改进。那么要解决的问题就是,如何限制 \(\theta'\)\(\theta\) 的步长在合理范围内。


TRPO (trust region policy optimization ,信任区域策略优化) 提出了一种使用 KL 散度(相对熵) 约束 \(\theta\)\(\theta'\) 的距离的方式:

\[\begin{aligned} \max &\ J^{\theta'}(\theta) = \mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta'}(s_t,a_t)\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right]\\ \mathbf{s.t.} &\ D_{\mathrm{KL}}(\pi_{\theta'} || \pi_{\theta}) < \delta \end{aligned}\]

问题是,这个优化问题很难求解,又要泰勒展开近似,又要共轭梯度法、线性搜索等,相当复杂。

而 PPO (proximal polical optimization,近端策略优化) 基于 TRPO 的思想,算法实现简单得多,效果和 TRPO 能一样好,因此成为了非常流行的强化学习算法。PPO 的优化问题为:

\[\max \ J^{\theta'}(\theta) = \mathbb{E}_{(s_t,a_t)\sim\pi_{\theta'}}\left[A^{\theta'}(s_t,a_t)\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}\right] - \beta \cdot D_{\mathrm{KL}}(\pi_{\theta'} || \pi_{\theta})\]

Question

Q:为什么要用 KL 散度,而不是直接用 \(\left\|\theta-\theta'\right\|\) 的 L1 或者 L2 范数来计算两个参数的距离?

A:因为我们需要考虑的不是参数上的距离,而是行为上的距离,即给定一个状态,两组参数对应的策略输出动作的差异。而参数和策略的变化不是线性相关的,有时候参数稍微变化一点,策略就大不相同。因此,我们需要用更合理的 KL 散度而非参数的范数距离,描述两个参数的“距离”。

Note

TRPO 和 PPO 都是同策略(on-policy)算法。虽然优化目标中有重要性采样,但因为它们只用到了上一轮策略的数据,并且用于采样的行为策略 \(\theta'\) 和待更新的目标策略 \(\theta\) 非常接近,所以它们仍然是同策略算法。

PPO 策略有两个主要的变种,分别是 PPO 惩罚和 PPO 截断。

PPO-penalty

\[\begin{aligned} J_{\mathrm{PPO}}^{\theta^{k}}&=J^{\theta^{k}}(\theta)-\beta \cdot D_{\mathrm{KL}}(\pi_{\theta^{k}} || \pi_{\theta})\\ J^{\theta^k}(\theta)&\approx \sum_{(s_t,a_t)}\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta^{k}}(a_t|s_t)}A^{\theta^{k}}(s_t,a_t) \end{aligned}\]

为什么期望在这里变成直接求和了?

PPO-penalty 的流程如下。

首先初始化一个策略参数 \(\theta^0\) 。在每个迭代中,用上一次的训练结果 \(\theta^k\) 与环境交互,得到大量的状态-动作对,并以此估计 \(A^{\theta^k}(s_t,a_t)\) . 接下来,使用 PPO 的优化公式更新一次参数。

这里要注意,策略梯度算法只能更新一次参数,但是 PPO 可以用上一组数据更新很多次参数,想办法最大化目标函数,因为我们有重要性采样。

此外,还有一个自适应调整参数 \(\beta\) 的方法:若 \(D_{\mathrm{KL}}(\pi_{\theta^{k}}||\pi_{\theta})\) 小于 \(\min D_{\mathrm{KL}}\) 阈值,则减小参数 \(\beta\) ,降低后一项的权重,防止它只优化 KL 散度;若 \(D_{KL}(\pi_{\theta^{k}}||\pi_{\theta})\) 大于 \(\max D_{\mathrm{KL}}\) 阈值,则增大参数 \(\beta\) ,提升后一项的权重,保证 \(\theta\)\(\theta^{k}\) 的 KL 散度在一定范围内。

PPO-clip

PPO 截断算法与上文不同,无需计算 KL 散度。其要最大化的目标函数为:

\[J^{\theta^{k}}_{\mathrm{PPO}2}(\theta)\approx\sum_{(s_t,a_t)}\min\left[\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta'}(a_t|s_t)}A^{\theta^{k}}(s_t,a_t),\mathrm{clip}\left(\frac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta^{k}}(a_t|s_t)},1-\varepsilon,1+\varepsilon\right)A^{\theta^{k}}(s_t,a_t)\right]\]

\(\mathrm{clip(f,min,max)}\) 的意思是,若第一项 \(\mathrm{f}\) 小于第二项 \(\min\) ,则输出 \(\min\) ;若大于第三项 \(\max\) ,则输出 \(\max\) ;若都不满足,则输出自身 \(\mathrm{f}\) .

这个式子看着复杂,实际简单。其核心思路是限制 \(\theta^{k}\)\(\theta\) 的距离。

  • \(A^{\theta^k}(s_t,a_t) > 0\) ,我们希望增大这个状态-动作对的概率,也就是让 \(\pi_{\theta}(a_t|s_t)\) 越大越好。加上截断之后,我们限制 \(\dfrac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta^{k}}(a_t|s_t)}\) 的最大值为 \(1+\varepsilon\) ,从而限制了 \(\theta^{k}\)\(\theta\) 的距离。
  • \(A^{\theta^{k}}(s_t,a_t) < 0\) ,我们希望减小这个状态-动作对的概率,也就是 \(\pi_{\theta}(a_t|s_t)\) 越小越好。加上截断之后,我们限制\(\dfrac{\pi_{\theta}(a_t|s_t)}{\pi_{\theta^{k}}(a_t|s_t)}\) 的最小值为 \(1-\varepsilon\) ,从而限制了 \(\theta^{k}\)\(\theta\) 的距离。

大量实验表明,PPO-clip 优于 PPO-penalty .

PPO 算法是一个非常主流的强化学习算法,在各种情况下都能表现出良好的性能。