deep|强化学习--信赖域系方法(TRPO、PPO(附适合初学者阅读的完整PPO代码连接))

在前面的章节里,我们已经介绍了基于策略的强化学习算法,也提到了异策略强化学习需要满足的条件:由于重要性采样的关系我们希望每次更新的时候策略分布之间差距并不是很大,这实际上是一种约束,即我们希望能每次更新的时候不大幅度地改变分布的形态,基于这种考虑openai的前辈们提出了TRPO算法,但是TRPO算法会有一些缺陷,他拿二次函数去近似约束条件,拿一次函数近似待优化的损失函数,这种近似会造成收敛上的困难,于是便有了第二次smart的改进,得到PPO系列的算法,PPO算法也是当前openai的默认算法,是策略算法的最好实现
【deep|强化学习--信赖域系方法(TRPO、PPO(附适合初学者阅读的完整PPO代码连接))】PPO的完整代码,我已放在我的github上了,诚意之作,欢迎点星,欢迎fork,这份代码的可读性要好于openai的baseline,更适合于初学者以及想弄明白其中原理的人,不到500行代码。
TRPO算法 回顾策略梯度的方法,根据之前的介绍我们知道在策略梯度中我们的更新满足如下关系:
θ n e w = θ o l d + α ? θ J \theta_{new}=\theta_{old}+\alpha\nabla_\theta J θnew?=θold?+α?θ?J
策略梯度的硬伤就在于更新步长 α \alpha α,当步长选的不合适的时候更新的参数会更差,因此很容易导致越学越差,最后崩溃,那什么样的步长叫做合适的步长呢,试想我们如果能找到一种步长,使他每次更新时都能保证回报函数单调递增,这样的步长就是好步长。TRPO的核心就是解决这个问题。
我们用 τ \tau τ来表示一个状态行为序列,或者说一条轨迹,那么某种策略下的期望回报可以看做是如下式子:
η ( π ~ ) = E τ ∣ π ~ [ ∑ t = 0 ∞ γ t ( r ( s t ) ) ] \eta(\tilde \pi)= E_{\tau|\tilde\pi}[\sum\limits_{t=0}^{\infty}\gamma^t(r(s_t))] η(π~)=Eτ∣π~?[t=0∑∞?γt(r(st?))]
既然TRPO的根本目的是为了使每次更新的回报函数单调不减,那么一个很自然的想法是将新的策略对应的回报函数分解成原来策略的回报函数加一个其他项,那么只要保证新的策略的其他项是大于零的,我们就得到了一个一直提升策略的方案。
在这种思想的引导下,我们可以得到如下等式:
η ( π ~ ) = η ( π ) + E τ ∈ π ~ [ ∑ t = 0 ∞ γ t A π ( s t , a t ) ] \eta(\tilde\pi)=\eta(\pi)+E_{\tau\in{\tilde\pi}}[\sum\limits_{t=0}^{\infty}\gamma^tA_{\pi}(s_t,a_t)] η(π~)=η(π)+Eτ∈π~?[t=0∑∞?γtAπ?(st?,at?)]
其中
A π ( s , a ) = Q π ( s , a ) ? V π ( s ) = E s ′ ~ P ( s ′ ∣ s , a ) [ r ( s ) + γ V π ( s ′ ) ? V π ( s ) ] A_{\pi}(s,a) = Q_{\pi}(s,a) - V_{\pi}(s) = E_{s' \sim P(s' |s,a)}[r(s)+\gamma V^{\pi}(s' )-V^{\pi}(s)] Aπ?(s,a)=Qπ?(s,a)?Vπ?(s)=Es′~P(s′∣s,a)?[r(s)+γVπ(s′)?Vπ(s)]
整个公式的证明稍许复杂不做详述。
我们将公式写开可以得到:
η ( π ~ ) = η ( π ) + ∑ t = 0 ∞ ∑ s P ( s t = s ∣ π ~ ) ∑ a π ~ ( a ∣ s ) γ t A π ( s , a ) \eta(\tilde\pi)=\eta(\pi)+\sum_{t=0}^{\infty}\sum\limits_s P(s_t=s|\tilde\pi)\sum\limits_a\tilde\pi(a|s)\gamma^t A_{\pi}(s,a) η(π~)=η(π)+t=0∑∞?s∑?P(st?=s∣π~)a∑?π~(a∣s)γtAπ?(s,a)
很容易进一步变形得到
η ( π ~ ) = η ( π ) + ∑ s ρ π ~ ( s ) ∑ a π ~ ( a ∣ s ) A π ( s , a ) \eta(\tilde\pi)=\eta(\pi)+\sum_s\rho_{\tilde\pi}(s)\sum\limits_a\tilde\pi(a|s)A^{\pi}(s,a) η(π~)=η(π)+s∑?ρπ~?(s)a∑?π~(a∣s)Aπ(s,a)
其中 ρ π ( s ) = P ( s 0 = s ) + γ P ( s 1 = s ) + γ 2 P ( s 2 = s ) + . . . \rho_{\pi}(s)=P(s_0=s)+\gamma P(s_1=s)+\gamma^2P(s_2=s)+... ρπ?(s)=P(s0?=s)+γP(s1?=s)+γ2P(s2?=s)+...
注意这里s是由新分布产生的,对新分布有很强的依赖性。这个公式其实在应用中完全无法达到,因为我们是为了得到新的策略,所以这里的其他项完全无从所知,为此,TRPO采取了一些技巧来解决这个问题。
下面我们来介绍TRPO论文中的四个技巧:

  1. 在原式中计算 ρ π ~ ( s ) \rho_{\tilde\pi}(s) ρπ~?(s)时,我们需要新的策略,而新策略目前还未知,因此,我们可以利用旧策略来代替新策略,因为两者相差并不是很大。
  2. 利用重要性采样处理动作分布
    注意到:
    ∑ a π ~ θ ( a ∣ s n ) A θ o l d ( s n , a ) = E a ~ q [ π ~ θ ( a ∣ s n ) π θ o l d ( a ∣ s n ) A θ o l d ( s n , a ) ] \sum\limits_a \tilde\pi_{\theta}(a|s_n)A_{\theta_{old}}(s_n,a)=E_{a\sim q}[\frac{\tilde\pi_{\theta}(a|s_n)}{\pi_{\theta_{old}}(a|s_n)}A_{\theta_{old}}(s_n,a)] a∑?π~θ?(a∣sn?)Aθold??(sn?,a)=Ea~q?[πθold??(a∣sn?)π~θ?(a∣sn?)?Aθold??(sn?,a)]

    L π ( π ~ ) = η ( π ) + E s ~ ρ θ o l d , a ~ π θ o l d [ π ~ θ ( a ∣ s n ) π θ o l d ( a ∣ s n ) A θ o l d ( s n , a ) ] L_{\pi}(\tilde\pi)=\eta(\pi)+E_{s\sim\rho_{\theta_{old}},a\sim\pi_{\theta_{old}}}[\frac{\tilde\pi_{\theta}(a|s_n)}{\pi_{\theta_{old}}(a|s_n)}A_{\theta_{old}}(s_n,a)] Lπ?(π~)=η(π)+Es~ρθold??,a~πθold???[πθold??(a∣sn?)π~θ?(a∣sn?)?Aθold??(sn?,a)]
    L π ( π ~ ) L_{\pi}(\tilde\pi) Lπ?(π~)与 η ( π ) \eta(\pi) η(π)的唯一区别是状态分布的不同,事实上 L π ( π ~ ) L_{\pi}(\tilde\pi) Lπ?(π~)是 η ( π ) \eta(\pi) η(π)的一阶近似。因此在 θ o l d \theta_{old} θold?附近,能改善 L L L的策略也能改善 η \eta η,下面一个核心的问题是,步长是多少?
    为此,我们引入一个非常重要的不等式:
    η ( π ~ ) ≥ L π ( π ~ ) ? C D K L m a x ( π , π ~ ) \eta(\tilde\pi)\ge L_{\pi}(\tilde\pi)-CD^{max}_{KL}(\pi,\tilde\pi) η(π~)≥Lπ?(π~)?CDKLmax?(π,π~)
    其中 C = 2 ? γ ( 1 ? γ ) 2 C=\frac{2\epsilon\gamma}{(1-\gamma)^2} C=(1?γ)22?γ?,而 D K L m a x ( π , π ~ ) D^{max}_{KL}(\pi,\tilde\pi) DKLmax?(π,π~)为每个状态下动作分布的最大值。
    这个不等式的证明比较繁琐,等博主有时间的时候再把公式打上去,我们先默认这个公式是对的,有了这个非常重要的公式,我们接下来就可以通过一些手段得到一个单调递增的策略序列。
    我们记 M i ( π ) = L π i ( π ~ ) ? C D K L m a x ( π i , π ~ ) M_i(\pi)= L_{\pi_i}(\tilde\pi)-CD^{max}_{KL}(\pi_i,\tilde\pi) Mi?(π)=Lπi??(π~)?CDKLmax?(πi?,π~)
    我们容易得到
    η ( π i + 1 ) ≥ M i ( π i + 1 ) , 且 η ( π i ) = M i ( π i ) \eta(\pi_{i+1})\ge M_i(\pi_{i+1}),且\eta(\pi_i)=M_i(\pi_i) η(πi+1?)≥Mi?(πi+1?),且η(πi?)=Mi?(πi?)则我们有
    η ( π i + 1 ) ? η ( π i ) ≥ M i ( π i + 1 ) ? M ( π i ) \eta(\pi_{i+1})-\eta(\pi_i)\ge M_i(\pi_{i+1})-M(\pi_i) η(πi+1?)?η(πi?)≥Mi?(πi+1?)?M(πi?)
    有了这个等式一切都好办了,我们只需要在下一步的策略中找到一个是当前 M i M_i Mi?最大的策略,则有上面的不等式,我们将很容易得到我们的策略的期望回报是单调递增的。
    于是,寻找策略的过程被我们被我们完全转换成了一个不断寻找函数最大值的过程。下面具体来看一下这个最大值问题
    我们希望找到参数 θ \theta θ满足
    max ? θ [ L θ o l d ? C D K L m a x ( θ o l d , θ ) ] \max\limits_{\theta}[L_{\theta_{old}}-CD^{max}_{KL}(\theta_{old},\theta)] θmax?[Lθold???CDKLmax?(θold?,θ)]
    在TRPO原文里,为了使这个问题更加数值可解,于是将原问题等效为了
    \begin{equation}
    \max\limits_{\theta}E_{s\sim\rho_{\theta_{old}},a\sim\pi_{\theta_{old}}}[\frac{\tilde\pi_{\theta}(a|s_n)}{\pi_{\theta_{old}}(a|s_n)}A_{\theta_{old}}(s_n,a)]\
    满足 D_{KL}^{max}(\theta_{old},\theta)\le \eta
    \end{equation}
    需要注意的是,实际应用中,我们的状态有无穷多个,也就是约束条件有无穷多个,这在实际优化过程是不可行的。
  3. TRPO的第三技巧是利用平均KL散度代替最大kl散度,也就是我们希望在之前的画面的里的散度的平均。
  4. TRPO的第四个技巧是对约束问题二次近似,非约束问题一次近似,这是凸优化的一种常见改法。最后TRPO利用共轭梯度的方法进行最终的优化。
对于一个初探强化学习的旁观者已经能够感受到TRPO实现上的种种近似所带来的误差,以及求解一个约束优化问题的困难,因此一种相比于TRPO理论更简洁,具体操作更简单,实验效果更优的算法应运而生,这就是PPO算法,PPO算法也是目前openai的默认算法,在迁移场景的时候,他们会默认优先使用这种算法。
PPO算法 PPO1
我们首先将TRPO需要处理的问题列一下:
L K L P E N ( θ ) = E t [ π ~ θ ( a ∣ s n ) π θ o l d ( a ∣ s n ) A θ o l d ( s n , a ) ? β K L [ π θ o l d , π θ ] ] L^{KLPEN}(\theta)={E}_t[\frac{\tilde\pi_{\theta}(a|s_n)}{\pi_{\theta_{old}}(a|s_n)}A_{\theta_{old}}(s_n,a)-\beta KL[\pi_{\theta_{old}},\pi_{\theta}]] LKLPEN(θ)=Et?[πθold??(a∣sn?)π~θ?(a∣sn?)?Aθold??(sn?,a)?βKL[πθold??,πθ?]]
PPO算法的思想很简单,既然TRPO认为在惩罚的时候有一个超参数 β \beta β难以确定,因而选择了限制而非惩罚,所以造成了很多羁绊,那么有没有什么好的方法能够避免超参数的选择而自适应地决定 β \beta β 呢,答案是有的,我们记
d = E t [ K L [ π θ o l d , π θ ] ] d=E_t[KL[\pi_{\theta_{old}},\pi_{\theta}]] d=Et?[KL[πθold??,πθ?]]
d t a r g e t d_{target} dtarget?为一个目标值,当我们的 d ≤ d t a r g e t / 1.5 d \le d_{target}/1.5 d≤dtarget?/1.5时,用 β / 2 \beta/2 β/2更新beta,反之,用 2 β 2\beta 2β更新 β \beta β
PPO2
除此之外,原论文中还提出了另一种的方法来限制每次更新的步长,我们一般称之为PPO2,论文里说PPO2的效果要比PPO1要好,所以我们平时说PPO都是指的是PPO2,PPO2的思想也很简单,思想的起点来源于对表达式的观察。我么记 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?)?,所以 r ( θ o l d ) = 1 r(\theta_{old})=1 r(θold?)=1
我们需要考虑
L C L I P ( θ ) = E t [ min ? ( r t ( θ ) A t , c l i p ( r t ( θ ) , 1 ? ? , 1 + ? ) A t ) ] L^{CLIP}(\theta)=E_{t}[\min(r_t(\theta)A_t,clip(r_t(\theta),1-\epsilon,1+\epsilon)A_t)] LCLIP(θ)=Et?[min(rt?(θ)At?,clip(rt?(θ),1??,1+?)At?)]
在这种夹的情况下可以保证两次更新之间的分布差距不大

    推荐阅读