132

文章目录

  1. 摘要
  2. 背景知识
  3. 一般优势估计(GAE)
    1. 基本公式
    2. GAE
      1. 定理一
      2. 优势函数估计
    3. 值函数估计
    4. python 实现
  4. 实验
  5. 引用

摘要

强化学习中常用的策略梯度算法有两个主要的挑战:

  1. 算法需要大量样本支撑。以降低训练过程中的样本方差大的问题
  2. 稳定训练困难。在实际训练过程中,我们经常可以看到模型得到的奖励值波动非常大

对于第一个挑战,本文通过设计的值函数,可以以少量偏差的损失为代价来换取方差的降低。对于第二个问题,本文提出对于策略函数和值函数都适用可信域优化的方法,来对于神经网络进行优化。

背景知识

强化学习中我们通常的目标是去优化一个策略所带来的平均总收益。该目标的一个困难之处在于行为(action)与其带来的影响,也就是奖励(reward),基本都不是同时发生的。产生奖励的时间与行为发生的时间之间通常会经过一段较长的时间间隔。这也就是强化学习中的credit assignment problem (CAP)问题。值函数(value function)为解决此问题带来了一个非常优雅的解决方案。值函数以环境的一个状态表示为输入,输出一个标量以衡量一个状态的价值。值函数直接切断了行为与未来可能的状态以及后续一些行为之间的关系,因此行为只需关心当前时刻所得到的奖励,将未来状态的价值判断都交给值函数去衡量。在本篇论文中,算法考虑去优化一个参数化的策略(比如神经网络),并且使用值函数来帮助预估策略改进的质量。

使用参数化的随机策略算法(parameterized stochasitc policy,与下文的actor-critic算法中引入值函数的算法相对应)时,我们是可以得到一个总回报期望的一个无偏估计的。

无偏与有偏

理论上,我们进行优化时,希望最大化如下收益:

$$ R_\theta = \sum_{t=0}^{\infty}r_t $$

该公式显然是总收益的无偏估计。我们在使用此公式来作为目标进行优化时,会遇到以下一些问题:

  1. 在某些场景下,$R_\theta$可能会趋于无穷大,这显然我们使用神经网络无法处理
  2. 一般,我们在使用策略梯度算法时,我们希望某个行为(action)可以和特定时间段内的收益(或损失)联系起来,可能某个行为在超过一定时间后就不再有任何影响了。而上面的公式将所有步骤的收益同等看待。

基于此,我们在使用策略梯度算法时,一般会使用如下的带衰减的收益:

$$ R_\theta^{\gamma} = \sum_{t=0}^{\infty}\gamma^t r_t, \gamma \in (0, 1) $$

该公式显然与我们无偏估计的收益不等,它是有偏的。显然$\gamma$越小,偏差越大。$\gamma=0$时,表示算法只关注当前利益,对于未来可能的收益并不去管。

使用期望收益的无偏估计来进行计算,看起来很好,但不幸的是,$R_{\theta}$的方差非常大。我们可以将每一个$r_t$当作一个随机变量来看,显然随着$t$越来越大,$R_\theta$的方差是单调增的。在$R_\theta^\gamma$中,单步的收益$r_t$前面有一个参数$\gamma$,因此随着$t$的增长,变量$\gamma^t r_t$的方差显然也会呈指数级递减。$R_\theta^\gamma$引入$\gamma$后,可以看作是使用引入偏差来降低了方差。小的方差可以让策略梯度算法的学习过程更加稳定。

actor-critic这一类算法中,引入了值函数,前面我们提到了值函数的一些好处。这里说一下它的缺点。值函数和策略函数一样,在策略梯度算法中,一般我们会直接用一个神经网络来近似这两个函数,使用大量的样本来训练这两个模型。其中我们称策略函数为actor,值函数为critic。使用值函数后,我们的目标函数可以改为如下形式的:

$$ R_\theta = r_t + V(s_{t+1}) $$

其中$s_{t+1}$表示$t+1$步的状态。该公式中只有两个变量,显然方差大大降低了。但是由于值函数$V$是学习而来的,它与实际的值函数之间存在着偏差,显然在训练初期,这个偏差还比较大。在一些情况下,我们可以通过产生大量的样本数据来弥补方差大的缺陷,但是偏差确实无法弥补的。

基于此,本文提出了一类策略梯度估计算法,可以让用户可以通过调节参数来来平衡方差与偏差,文中称之为一般优势估计(generalized advantage estimator/GAE)。

一般优势估计(GAE)

基本公式

策略梯度的公式,通常有如下形式:

$$ g = \mathbb{E}\left[ \sum_{t=0}^\infty \Psi_t \nabla_\theta log\pi_\theta(a_t|s_t) \right], $$

其中,$\Psi_t$的形式可以是:

$$ \sum_{t=0}^{\infty}r_t: 总奖励 $$
$$ \sum_{t^\prime=t}^{\infty}r_{t^{\prime}}: 行为a_t 后的总奖励 $$
$$ \sum_{t=0}^{\infty}r_t - b(s_t): 前一个公式带基线的版本 $$
$$ Q^\pi(s_t, a_t): Q 函数版本 $$
$$ A^\pi(s_t, a_t): 优势函数版本 $$
$$ r_t + V^\pi(s_{t+1}) - V^{\pi}(s_t):TD残差版本 $$

其中,值函数:

$$ V^\pi(s_t) := \mathbb{E}_{s_{t+1:\infty}, a_{t:\infty}} \sum_{l=0}^{\infty}r_{t+l} $$

Q函数:

$$ Q_{s_t, a_t}^{\pi} := \mathbb{E}_{s_{t+1:\infty}, a_{t+1:\infty}} \sum_{l=0}^{\infty}r_{t+l} $$

优势函数:

$$ A^\pi (s_t, a_t) := Q^\pi(s_t, a_t) - V^\pi(s_t, a_t) $$

如果公式大家不熟悉,建议去回顾下策略梯度算法的基础知识。

GAE

当我们选择$\Psi_t = A^\pi(s_t, a_t)$时,梯度的方差是最小的(可参考这篇blog[2],里面有一些通俗的解释)。在实际使用时,优势函数是未知的,因此无法直接使用,我们需要一个估计来替代未知的优势函数(advantage function)。

首先,我们引入衰减参数$\gamma$,这在很多论文、书籍里都用了。正如我们前文分析的引入$\gamma$参数可以降低方差(虽然引入了偏差)。此时,我们的值函数、Q函数、优势函数公式变为:

$$ V^{\pi, \gamma}(s_t) := \mathbb{E}_{s_{t+1:\infty}, a_{t:\infty}} \sum_{l=0}^{\infty}\gamma^{l}r_{t+l} $$
$$ Q_{s_t, a_t}^{\pi,\gamma} := \mathbb{E}_{s_{t+1:\infty}, a_{t+1:\infty}} \sum_{l=0}^{\infty}\gamma^{l}r_{t+l} $$
$$ A^{\pi, \gamma} (s_t, a_t) := Q^{\pi, \gamma}(s_t, a_t) - V^{\pi, \gamma}(s_t, a_t) $$

此时,策略梯度公式为:

$$ g^{\gamma} := \mathbb{E}_{s_{0:\infty}, a_{0:\infty}} \left[ \sum_{t=0}^{\infty}A^{\pi, \gamma}(s_t, a_t)\nabla_\theta log\pi_\theta(a_t|s_t) \right] $$

下面,我们讨论如何得到一个$A^{\pi, \gamma}$的估计。

定理一

首先,我们定义$\gamma$-估计:

我们说估计$\hat{A}_t$为$\gamma$-估计,当其满足:

$$ \begin{align} & \underset{s_{0:\infty}, a_{0:\infty}}{\mathbb{E}}\left[ \hat{A}_t(a_{0:\infty}, s_{0:\infty})\nabla_\theta log\pi_\theta(a_t|s_t) \right] \\ =& \underset{s_{0:\infty}, a_{0:\infty}}{\mathbb{E}}\left[ A^{\pi,\gamma}_t(a_{0:\infty}, s_{0:\infty})\nabla_\theta log\pi_\theta(a_t|s_t) \right] \end{align} $$

也就是说如果由一个估计$\hat{A}_t$所得到的梯度在期望条件下与$A_t^{\pi, \gamma}$所得到的一致(我们得到了$A_t^{\pi, \gamma}的一个无偏估计$),那么我们称它为$\gamma$-估计。

显然$\gamma$-估计就是我们想要找到的函数族,以下定理给出了$\gamma$-估计的一个充分条件:

定理一: 如果估计$\hat{A}_t$可以写成如下形式

$$ \hat{A}_t(s_{0:\infty}, a_{0:\infty}) = Q_t(s_{0:\infty}, a_{0:\infty}) - b_t(s_{0:t}, a_{0:t-1}) $$

并且

$$ \mathbb{E_{s_{t+1, \infty}, a_{t+1, \infty}|s_t,a_t}}[Q_t(s_{t:\infty}, a_{t:\infty})] = Q^{\pi, \gamma}(s_t, a_t) $$

那么$\hat{A}$就是$\gamma$-估计。

该定理说明只要$\hat{A}$可以拆分成$Q$和$b$两部分,其中$Q$进依赖于$t$时刻(包含$t$)之后的状态与行动,$b_t$进依赖于$s_t$以前(包含$s_t$)的状态与行动,那么该估计就是$A^{\pi, \gamma}$的一个无偏估计。

其实$A^{\pi, \gamma}$由于引入了衰减系数$\gamma$,其本身也是一个有偏估计。

另外大家看公式注意一下下标。

关于定理证明

该公式的证明,论文附录B有给出,实际上我没看懂。大致思想是b那部分求期望后为0,所以不会引入偏差。Q那部分求期望后等于$A^{\pi, \gamma}$ (另外文中给出的是无衰减版本,也就是不带$\gamma$的版本),我猜带衰减的版本应该也成立吧。

b 求期望后为零的证明,如果原文没看明白的,大家可以参考引用[2],那篇博客里写的比较清楚。

Q 那部分等以后有时间,我再去研究下怎么整的。

优势函数估计

设$V$为值函数,定义$\delta_t^V = r_t + \gamma V(s_{t+1}) - V(s_t)$,此时中如果$V=V^{\pi, \gamma}$,那么$\delta_t^{V}$就是一个$\gamma$-估计。证明如下:

$$ \begin{align} &\ \mathbb{E}\left[ \delta_t^{V^{\pi, \gamma}} \right]\\ =&\ \mathbb{E}[r_t + \gamma V^{\pi, \gamma}(s_{t+1}) - V^{\pi, \gamma}(s_t)]\\ =&\ \mathbb{E}[Q^{\pi, \gamma}(s_t, a_t) - V^{\pi, \gamma}(s_t)]\\ =&\ A^{\pi, \gamma}(s_t, a_t) \end{align} $$

由于实际情况下,$V^{\pi, \gamma}$是未知的,因此,为了得到一个无偏的估计,我们需要一些其它操作。首先,定义估计簇$\hat{A}^{(k)}$:

$$ \begin{align} \hat{A}^{(1)}_t & = r_t + \gamma V(s_{t+1}) - V(s_t)\\ \hat{A}^{(2)}_t & = r_t + \gamma r_{t+1} + \gamma^2 V(s_{t+2}) - V(s_t)\\ \cdots &= \cdots \\ \hat{A}^{(\infty)}_t & = r_t + \gamma r_{t+1} + \gamma^2 r_{t+2} - V(s_t)\\ \end{align} $$

也就是:

$$ \begin{align} \hat{A}^{(k)}_t & = \sum_{l=0}^{\infty}\gamma^{l}r_{t+l} + \gamma^k V(s_{t+k}) - V(s_t) \\ & \overset{(i)}{=} \sum_{l=0}^{\infty}\gamma^{l}\delta_{t+l}^V \end{align} $$

上式中$(i)$很容易验证,大家可以从下往上推。当$k \to \infty$时,有

$$ \lim_{k \to \infty} \hat{A}_t^{(k)} = \sum_{l=0}^{\infty}\gamma^{l}r_{t+l} - V(s_t) $$

根据定理一,我们有$\hat{A}_t^{(\infty)}$为一个$\gamma$-估计。直观讲,$k$越大,我们得到的值越准确,但是随着变量的增多,$\hat{A}_t^{(k)}$的方差越来越大!那么,如何在方差与偏差之间进行平衡呢?既然估计族$\hat{A}_t^{(k)}$中的每一个估计都是偏差与方差的一个平衡点,那么索性就都用起来。

下面我们看本文的重点GAE的定义。GAE被定义为估计簇$\hat{A}_t^{(k)}$的一个加权和:

$$ \begin{align} \hat{A}_t^{GAE(\gamma, \lambda)} :=&\ (1-\lambda)\left( \hat{A}_t^{(1)} + \lambda \hat{A}_t^{(2)} + \lambda^2 \hat{A}_t^{(3)} + \cdots \right)\\ \overset{将上面(i)变换带入}{=} &\ (1-\lambda)(1+\lambda + \lambda^2 + \cdots)\left( \delta_t^V + \gamma\lambda \delta_{t+1}^V + \gamma^2 \lambda^2 \delta_{t+2}^V + \cdots \right)\\ \overset{(1)}{=} &\ (1-\lambda)\left(\frac{1}{1-\lambda} \right)\left( \delta_t^V + \gamma\lambda \delta_{t+1}^V + \gamma^2 \lambda^2 \delta_{t+2}^V + \cdots \right)\\ =&\ \sum_{l=0}^{\infty}(\gamma \lambda)^l \delta_{t+l}^V \end{align} $$

上式中$(1)$变换,只有在$\lambda \lt 0$时成立。

$GAE$的结果非常简洁奈斯,就是残差项的指数衰减求和。

$GAE(\gamma, \lambda)$有两个特例:

  • $GAE(\gamma, 0)$: 此时$\hat{A}_t = \delta_t^V$,退化为TD残差,虽然存在偏差,但是由于包含的变量项数较少,因此方差小
  • $GAE(\gamma, 1)$: 此时$\hat{A}_t = \sum_{l=0}^{\infty}\gamma^l \delta_{t+l}^V = \sum_{l=0}^{\infty}\gamma^{l}r_{t+l} - V(s_t)$,这其实就是$\hat{A}_t^{(\infty)}$是个无偏估计,但由于变量太多,因此该估计方差较大

因此$\lambda$参数可以作为调节偏差与方差的一个超参数。

上面的公式中,我们并没有把$\lambda$和$\gamma$参数合成一个参数,原因是$\delta_t$是与$\gamma$相关的。另外,GAE在实际使用中很可能并没有退化后的$GAE(\gamma, 0)$或$GAE(\gamma, 1)$好用,这个理论和实际的差距还是挺大的。

论文中还从reward shaping角度介绍了一波$GAE$,感兴趣的同学可以去看看。

值函数估计

为了在策略梯度算法中使用GAE,我们还需要一个值函数,实际使用时,一般我们会用一个神经网络来近似值函数$V_\phi$,其中$\phi$为值函数的参数。在训练时,我们会采样得到一组路径$\tau_i, i=0, 1, 2, \cdots$

$$ \tau_i = (s_0, a_0, r_0, s_1, a_1, r_1, \ldots) $$

由此可以得到值函数的近似值 $\hat{V}_t = \sum_{l=0}^\infty\gamma^lr_{t+l}$,训练时我们一般会最小化$\hat{V}_t$与$V_\phi$之间的$MSE$。在本文中,作者将可信域的概念引入了。可信域是为了防止经过一次优化后的模型与原来的模型之间差别太大,可以用来防止模型太过拟合于当前批的数据。之前一篇比较著名的论文(Trust Region Policy Optimization, 有时间我们再分享)是将其用在了策略网络中,而本文将其扩展到了值网络中。

形式化来说,我们希望找到最优的$\phi$:

$$ argmin_\phi \sum_{n=1}^{N}\lVert V_\phi(s_n) - \hat{V}_n \lVert_2^2 $$

满足:

$$ \frac{1}{N}\sum_{n=1}^N\frac{\lVert V_\phi(s_n) - \hat{V}_{\phi_{old}}(s_n) \lVert_2^2}{2\sigma^2} \le \epsilon $$

其中$\hat{V}_{\phi_{old}}$为更新前的值网络模型,$\sigma^2 = \frac{1}{N}\sum_{n=1}^N\lVert V_{\phi_{old}(s_n)} - \hat{V}_n \lVert_2^2$。

这是个典型的条件优化问题,此处不在赘述解法,文中使用了共轭梯度算法来得到一个近似解。值网络一般与策略网络是分开优化的。但在很多情况下,值网络与策略网络会共享特征提取部分的代码,只有在最终输出策略/值时使用不同的全连接层。

python 实现

GAE虽然看起来复杂,但是实现起来非常的简洁,下面我们给出实现代码:

import numpy as np

def gae(csv, nsv, rewards, dones, gamma, lmbd):
    """返回策略网络与值网络优化所用参数

    参数, (所有参数都是 numpy array 类型):
        csv: current state values: 值函数输出的当前状态的预测值
        nsv: next state values: 下一个状态的预测值
        rewards: 每一步的奖励
        dones: 每一步是否结束一轮(比如游戏结束),结束用1表示,未结束用0表示,
            GAE中不存在done这个概念,但是在实现时我们一般会跑多轮作为一组数据,
            所以,一轮结束时,要记录下结束的位置
        gamma: 参数gamma
        lmbd: 参数 lambda (由于lambda 为python关键字,所以未使用)
    """
    g = 0
    advs = []
    masks = 1 - dones
    for i in range(done.shape[0])[::-1]:
        delta = rewards[i] + gamma * nsv[i] * masks[i] - csv[i]
        g = delta + gamma * lmbd * g * masks[i]
        advs += [g]
    advs = np.array(advs[::-1])

    return advs, advs + csv

实验

实验效果肯定很好啊,感兴趣看论文去。

引用

[1] Schulman, John, et al. "High-dimensional continuous control using generalized advantage estimation." arXiv preprint arXiv:1506.02438 (2015).

[2] Going Deeper Into Reinforcement Learning: Fundamentals of Policy Gradients https://danieltakeshi.github.io/2017/03/28/going-deeper-into-reinforcement-learning-fundamentals-of-policy-gradients/