从REINFORCE到PPO,看Policy Gradient的前世今生

从REINFORCE到PPO,看Policy Gradient的前世今生

Policy Gradient和Q-learning可以说是model-free RL的两大阵营。前者是off-line、on-policy的方法,后者是on-line、off-policy的方法。前者是策略迭代,关心的是策略网络的参数;后者是值迭代,关心的是值网络的输出。随着RL的不断发展,这两类方法在不断交错领跑的过程中交汇融合,不断给我们带来新的惊喜。

本文重点在介绍Policy Gradient方法,从其“初心”出发,通过一步步的推导来讲述新的算法。后半部分的重点将放在兼具漂亮理论基础和简洁代码实现的PPO方法上,欢迎RL入门级的小朋友们一起讨论学习!

Policy Gradient

如果你已经了解了DQN,也许会想到这样一个问题:为什么一定要用值函数来做决策(当然这个想法也是很自然的),为什么不绕过值函数直接用神经网络来表示策略呢?
当然,想要讨论清楚这个问题不是很容易,有很多不同的看法,感兴趣的小朋友可以看一下知乎上对问题RL两大类算法的本质区别?(Policy Gradient 和 Q-Learning)
南京大学俞杨老师的答案,很有启发性。

让我们再退一步,我们想要的东西到底是什么呢?其实就是让我们采取策略的期望收益最大化!

θ=argmaxθEτpθ(τ)r(τ)J(θ) θ ∗ = arg ⁡ max θ ⁡ E τ ∼ p θ ( τ ) r ( τ ) ⏟ J ( θ )

τ τ 表示一条样本轨迹,策略所影响的,是样本轨迹 τ τ 出现的概率,也就是 pθ(τ) p θ ( τ )

那么 r(τ) r ( τ ) pθ(τ) p θ ( τ ) 指的具体是什么呢?我们再进一步展开来写一下:

r(τ)=tr(st,at)pθ(τ)=p(s1)tπθ(at|st)p(st+1|st,at) r ( τ ) = ∑ t r ( s t , a t ) p θ ( τ ) = p ( s 1 ) ∏ t π θ ( a t | s t ) p ( s t + 1 | s t , a t )

注意,这里的 τ τ t t 的含义不同, τ τ 是样本轨迹, t t 是样本轨迹上的时间。仔细看 pθ(τ) p θ ( τ ) 我们就会发现,将概率展开以后实际上我们的策略可以影响的只有 πθ(at|st) π θ ( a t | s t ) ,也就是在状态 st s t 下采取动作 at a t 的概率。这也就是我们策略的数学表示。

REINFORCE

现在我们就可以再向前走一步,按照机器学习的一般思路,我已经定义好了我的目标函数 J(θ) J ( θ ) ,如果可以求出它的梯度 θJ(θ) ∇ θ J ( θ ) ,我们就可以梯度下降了!为了求梯度,我们将 J(θ) J ( θ ) 改写成积分的形式:

J(θ)θJ(θ)=Eτpθ(τ)r(τ)=pθ(τ)r(τ)dτ=θpθ(τ)r(τ)dτ=pθ(τ)θlogpθ(τ)r(τ)dτ=Eτpθ(τ)θlogpθ(τ)r(τ) J ( θ ) = E τ ∼ p θ ( τ ) r ( τ ) = ∫ p θ ( τ ) r ( τ ) d τ ∇ θ J ( θ ) = ∫ ∇ θ p θ ( τ ) r ( τ ) d τ = ∫ p θ ( τ ) ∇ θ log ⁡ p θ ( τ ) r ( τ ) d τ = E τ ∼ p θ ( τ ) ∇ θ log ⁡ p θ ( τ ) r ( τ )

这里用到了一个小技巧, θpθ(τ)=pθ(τ)θpθ(τ)pθ(τ)=pθ(τ)θlogpθ(τ) ∇ θ p θ ( τ ) = p θ ( τ ) ∇ θ p θ ( τ ) p θ ( τ ) = p θ ( τ ) ∇ θ log ⁡ p θ ( τ ) ,这样做的目的是把 pθ(τ) p θ ( τ ) 重新拿到外边来,就可以再写成期望的形式了。

现在公式中的自变量仍然是 τ τ ,实际应用中我们不可能直接对 τ τ 求导,因此我们再把 pθ(τ) p θ ( τ ) 带进来看看能不能将 τ τ 给替换为我们可以操作的 st s t at a t

θlogpθ(τ)θJ(θ)=θlogp(s1)0+tθlogπθ(at|st)+θlogp(st+1|st,at)0=tθlogπθ(at|st)=Eτpθ(τ)[tθlogπθ(at|st)][tr(st,at)] ∇ θ log ⁡ p θ ( τ ) = ∇ θ log ⁡ p ( s 1 ) ⏟ 0 + ∑ t [ ∇ θ log ⁡ π θ ( a t | s t ) + ∇ θ log ⁡ p ( s t + 1 | s t , a t ) ⏟ 0 ] = ∑ t ∇ θ log ⁡ π θ ( a t | s t ) ∇ θ J ( θ ) = E τ ∼ p θ ( τ ) [ ∑ t ∇ θ log ⁡ π θ ( a t | s t ) ] [ ∑ t r ( s t , a t ) ]

于是,我们也就得到了我们的第一个算法REINFORCE:

  1. 用参数为 θ θ 的策略 πθ(a|s) π θ ( a | s ) 采样N条样本轨迹 τi τ i
  2. 估计梯度 θJ(θ)1Ni(tθlogπθ(at|st))(tr(st,at)) ∇ θ J ( θ ) ≈ 1 N ∑ i ( ∑ t ∇ θ log ⁡ π θ ( a t | s t ) ) ( ∑ t r ( s t , a t ) )
  3. 更新参数 θθ+αθJ(θ) θ ← θ + α ∇ θ J ( θ ) ,重复1

可以将 θJ(θ) ∇ θ J ( θ ) 看成这样的两部分: tlogπθ(at|st) ∑ t log ⁡ π θ ( a t | s t ) 是改进策略的方向, tr(st,at) ∑ t r ( s t , a t ) 是改进策略的步长,回报大的就走一大步,回报小的就走一小步,回报为负就往反方向走一步。

Actor-Critic

REINFORCE方法缺点很多,它的效率是非常低的,其中一个非常重要的原因就是方差非常大。 tr(st,at) ∑ t r ( s t , a t ) 是每一次仿真的结果,如果效果好了就会对这一次仿真的所有决策奖励,效果不好了就会全部惩罚,这显然是有问题的。
让我们再来好好看一下 θJ(θ) ∇ θ J ( θ ) 的计算过程

θJ(θ)=Eτpθ(τ)[tθlogπθ(at|st)][t=0r(st,at)] ∇ θ J ( θ ) = E τ ∼ p θ ( τ ) [ ∑ t ∇ θ log ⁡ π θ ( a t | s t ) ] [ ∑ t ′ = 0 ∞ r ( s t ′ , a t ′ ) ]

如果 t2>t1 t 2 > t 1 πθ(at2|st2) π θ ( a t 2 | s t 2 ) 理论上是不会对 t1t=0r(st,at) ∑ t = 0 t 1 r ( s t , a t ) 产生影响的。因此上面的计算式可以改进成为

θJ(θ)=Eτpθ(τ)[tθlogπθ(at|st)t=tr(st,at)] ∇ θ J ( θ ) = E τ ∼ p θ ( τ ) [ ∑ t ∇ θ log ⁡ π θ ( a t | s t ) ∑ t ′ = t ∞ r ( s t ′ , a t ′ ) ]

实际上, Qt=t=tr(st,at) Q t = ∑ t ′ = t ∞ r ( s t ′ , a t ′ ) 和我们对Q因子的定义非常接近了,都是从时刻 t t 开始到结束时的收益。

我们已经减少了一些方差了,能不能再减小呢?我们都知道,对于随机变量 X X ,其方差 DX=EX2(EX)2 D X = E X 2 − ( E X ) 2 ,如果 EX2 E X 2 比较小的话,那么方差就会小了。自然想到给 r(τ) r ( τ ) 减去一个值,即 r(τ)r(τ)b r ( τ ) ← r ( τ ) − b ,选择合适的 b b (比如 1Nir(τi) 1 N ∑ i r ( τ i ) ),那么方差就会变小了。方差小了,结果会不会变呢?答案是不变的,我们来证明一下:

E[θlogπθ(τ)b]=πθ(τ)θlogπθ(τ)bdτ=θπθ(τ)bdτ=bθπθ(τ)dτ=bθπθ(τ)dτ=bθ1=0 E [ ∇ θ log ⁡ π θ ( τ ) b ] = ∫ π θ ( τ ) ∇ θ log ⁡ π θ ( τ ) b d τ = ∫ ∇ θ π θ ( τ ) b d τ = b ∫ ∇ θ π θ ( τ ) d τ = b ∇ θ ∫ π θ ( τ ) d τ = b ∇ θ 1 = 0

所以只要 b b 本身是与 τ τ 无关的,那么我们就可以这样做!上面的证明是以 τ τ 为自变量的,其实当我们用 Qt Q t 时一样可以推出这个结果。

b b 的选取成为了另一个问题。理论上可以推出一个最优的 b b ,不过应用中我们会用 Vt V t 估计 b b 。也就是说用另外的一个网络来估计 Q(st,at) Q ( s t , a t ) V(st)=Eatπθ(at|st)Q(st,at) V ( s t ) = E a t ∼ π θ ( a t | s t ) Q ( s t , a t ) ,这样就有

θJ(θ)=Eτpθ(τ)[tθlogπθ(at|st)[Q(st,at)V(st)])] ∇ θ J ( θ ) = E τ ∼ p θ ( τ ) [ ∑ t ∇ θ log ⁡ π θ ( a t | s t ) [ Q ( s t , a t ) − V ( s t ) ] ) ]

是不是看上去舒服多了?对DQN熟悉的小朋友们就可以用上熟悉的值网络了,不过这次我们的目的是通过估计值网络来帮助更新策略网络。

Q(st,at)V(st) Q ( s t , a t ) − V ( s t ) 实际上就是我们的优势函数 A(st,at) A ( s t , a t ) 。对于连续动作的问题, Q(st,at) Q ( s t , a t ) 是比较难用网络表示的,即使表示出来也难以由 Q(st,at) Q ( s t , a t ) 直接求出 V(st) V ( s t ) 。因此,有时候我们会选择直接估计 V(st) V ( s t ) ,用 r(st,at)+V(st+1)V(st) r ( s t , a t ) + V ( s t + 1 ) − V ( s t ) 来估计 A(st,at) A ( s t , a t ) 。注意,这里又是估计的量, r(st,at)+V(st+1)V(st) r ( s t , a t ) + V ( s t + 1 ) − V ( s t ) A(st,at) A ( s t , a t ) 之间是有偏的。自从我们选择了用估计的 Q(st,at) Q ( s t , a t ) 代替 t=tr(st,at) ∑ t ′ = t ∞ r ( s t ′ , a t ′ ) 开始,我们就一直在牺牲偏差来降低方差,以提高我们的学习速度。

Actor-Critic是一个算法框架,这里给出其中一种的算法流程:

  1. 用参数为 θ θ 的策略 πθ(a|s) π θ ( a | s ) 采样N个状态转移 {si,ai,ri,si} { s i , a i , r i , s i ′ }
  2. 更新值网络参数 ϕ ϕ 使得 Vϕ(si)ri+Vϕ(si) V ϕ ( s i ) ← r i + V ϕ ( s i ′ )
  3. 估计 A^(si,ai)=ri+V(si)V(si) A ^ ( s i , a i ) = r i + V ( s i ′ ) − V ( s i )
  4. 估计梯度 θJ(θ)1Niθlogπθ(ai|si)A^(si,ai) ∇ θ J ( θ ) ≈ 1 N ∑ i ∇ θ log ⁡ π θ ( a i | s i ) A ^ ( s i , a i )
  5. 更新参数 θθ+αθJ(θ) θ ← θ + α ∇ θ J ( θ ) ,重复1

除了用值函数来估计 A^(s,a) A ^ ( s , a ) ,Actor-Critic框架中至少还可以使用以下形式(我们基本上都讨论过了):

  1. t=0rt ∑ t = 0 ∞ r t —— 轨迹的总回报
  2. t=trt ∑ t ′ = t ∞ r t ′ —— 动作后的回报
  3. t=trtb(st) ∑ t ′ = t ∞ r t ′ − b ( s t ) —— 减去基线
  4. Qπ(st,at) Q π ( s t , a t ) —— 状态-行为值函数
  5. Aπ(st,at) A π ( s t , a t ) —— 优势函数
  6. rt+Vπ(st+1)Vπ(st) r t + V π ( s t + 1 ) − V π ( s t ) —— 时序差分误差(TD error)

PPO

截至目前,上述提到的算法都还有一些共同的问题。其中一个非常大的问题就是参数空间的距离并不等于策略空间的距离,也就是说在不同的状态下改变相同步长的网络参数,产生策略的概率改变是不同的,而且差异非常大!以下图为例,一个最简单的sigmoid函数输出在同样的参数步长下的输出是变化很大的!
从REINFORCE到PPO,看Policy Gradient的前世今生_第1张图片
再换句话说,我们希望可以找到一种方法,来自动调整参数空间的步长,以达到策略空间均匀变化的目的。

为了达到这样一个目标,我们需要知道不同的两个策略其目标函数的差异有多少,如果可以有效的评价出这个差值,那么我们就可以根据它来调整我们的策略了。幸运的是,两个策略目标函数的差值之间存在着这样一个关系

J(π)J(π)=Eτπ[t=0γtAπ(st,at)] J ( π ′ ) − J ( π ) = E τ ∼ π ′ [ ∑ t = 0 ∞ γ t A π ( s t , a t ) ]

这里 π π 是参数化的策略 πθ(at|st) π θ ( a t | s t ) π π ′ 则是更新后的策略。证明过程这里提示两点,一是 J(π)=Eτπ[t=0γtrt] J ( π ) = E τ ∼ π ′ [ ∑ t = 0 ∞ γ t r t ] ,二是 A(st,at)=rt+V(st+1,at+1)V(st,at) A ( s t , a t ) = r t + V ( s t + 1 , a t + 1 ) − V ( s t , a t ) ,代入上式即可。

下面的问题是,我们怎么利用上面这个关系呢?请注意,上式的采样是在新的策略 π π ′ 下进行的,但我们还不知道新的策略是什么怎么采样呢,这不是因果矛盾了吗?难道我们要一个一个策略去试选个最好的?当你想在不同的分布下去估计某个期望,那一定绕不开重要性采样(Importance Sampling),不懂的同学请自行百度。

我们引入一个新的概念,叫折扣状态分布,定义是 dπ(s)=(1γ)t=0γtP(st=s|π) d π ( s ) = ( 1 − γ ) ∑ t = 0 ∞ γ t P ( s t = s | π ) ,直观理解就是在时间上更近的地方考虑的更多一些。在这个分布下,就有关系如下:

J(π)J(π)=Eτπ[t=0γtAπ(st,at)]=11γEstdπ,atπ[Aπ(st,at)]=11γEstdπ,atπ[π(at|st)π(at|st)Aπ(st,at)] J ( π ′ ) − J ( π ) = E τ ∼ π ′ [ ∑ t = 0 ∞ γ t A π ( s t , a t ) ] = 1 1 − γ E s t ∼ d π ′ , a t ∼ π ′ [ A π ( s t , a t ) ] = 1 1 − γ E s t ∼ d π ′ , a t ∼ π [ π ′ ( a t | s t ) π ( a t | s t ) A π ( s t , a t ) ]

这一部分可能比较难理解,我们一步步来解释一下。第一个等号这里做的事情是将轨迹 τ τ 拆开到每一个时间步上来看,然后将 P(st=s|π) P ( s t = s | π ) 放到了求期望的角标里,也就是说考虑成了在 dπ(s) d π ′ ( s ) 这种折扣分布条件下的期望。第二步就是用了重要性采样,解决了我们上面说到的 π π ′ 我们还不知道的问题。

等等! at a t 是只和 π π 有关了,但是 st s t 不还是和 π π ′ 有关吗?是的。但 dπ(s) d π ( s ) dπ(s) d π ′ ( s ) 已经很接近了,理论证明如果 π π π π ′ 足够接近,那么其评价函数之差将满足

|J(π)(J(π)+Lπ(π))|CEst[DKL(π||π)] | J ( π ′ ) − ( J ( π ) + L π ( π ′ ) ) | ≤ C E s t [ D K L ( π ′ | | π ) ]
Lπ(π)=11γEstdπ,atπ[π(at|st)π(at|st)Aπ(st,at)] L π ( π ′ ) = 1 1 − γ E s t ∼ d π , a t ∼ π [ π ′ ( a t | s t ) π ( a t | s t ) A π ( s t , a t ) ]

其中 DKL(π||π) D K L ( π ′ | | π ) π π π π ′ 之间的KL散度,用以衡量两个分布之间的距离。现在,所有的分布中就没有需要从 π π ′ 进行采样的了。我们只需要计算一下更新参数后的 π π π π ′ 之间的比值已经KL散度,就可以估计两个策略之间的评价函数的差异了。

虽然现在已经很简单了,但 DKL(π||π) D K L ( π ′ | | π ) 这个东西还是有点让我们伤脑筋,毕竟每一次更新参数都要判断一下这个条件是不是满足。为了解决这个问题,又有一系列的方法出现,比如用近似的方法去估计出最优解,再比如将 DKL(π||π) D K L ( π ′ | | π ) 作为惩罚项加入到loss中。但是这些方法实现起来都比较麻烦,就是那种看都不想看一眼的麻烦。

于是,PPO就粉墨登场了。PPO其实就是近似的求解,原文中提到了两种方式来近似,一种是自动调整对KL散度的惩罚因子,一种是用clip的方法巧妙地构造了一个新的目标函数。因为第二种方法用过的都说好,我们重点来介绍一下它。

很简单,原来的方案中下一轮的参数 θk+1 θ k + 1 满足

θk+1=argmaxθLθk(θ)s.t.DKL(θk+1||θk)<δLθk(θ)=Eτπkt=0[πθ(at|st)πθk(at|st)Aπθk(st,at)] θ k + 1 = arg ⁡ max θ ⁡ L θ k ( θ ) s . t . D K L ( θ k + 1 | | θ k ) < δ L θ k ( θ ) = E τ ∼ π k ∑ t = 0 ∞ [ π θ ( a t | s t ) π θ k ( a t | s t ) A π θ k ( s t , a t ) ]

现在换一种近似的目标函数

θk+1=argmaxθLclipθk(θ)Lclipθk(θ)=Eτπkt=0[min(rt(θ)Aπθk(st,at),clip(rt(θ),1ϵ,1+ϵ)Aπθk(st,at))]rt(θ)=πθ(at|st)πθk(at|st) θ k + 1 = arg ⁡ max θ ⁡ L θ k c l i p ( θ ) L θ k c l i p ( θ ) = E τ ∼ π k ∑ t = 0 ∞ [ m i n ( r t ( θ ) A π θ k ( s t , a t ) , c l i p ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) A π θ k ( s t , a t ) ) ] r t ( θ ) = π θ ( a t | s t ) π θ k ( a t | s t )

不要被公式的长度给吓到,其实就是控制了 π π π π ′ 的比值,如果这两个的比值接近那么自然其KL散度也不比较小,反之就剪掉超过的部分,将其比值限制在一个小范围内。这里的 ϵ ϵ 常取0.1或0.2。原文中还做了对比实验,说明了不同目标函数之间的关系。读图我们可以看到当 ϵ ϵ 取得很小时, Lclipθk(θ) L θ k c l i p ( θ ) Lθk(θ)DKL(theta||thetak) L θ k ( θ ) − D K L ( t h e t a | | t h e t a k ) 是很接近的。
从REINFORCE到PPO,看Policy Gradient的前世今生_第2张图片

实验

至此,所有的理论部分都讲完了。我写了一个pytorch在pendulum问题上的小实验,大家感兴趣的可以看一下我的github。训练的效果、训练过程的曲线,还有学到的value和action都贴在了下面。
从REINFORCE到PPO,看Policy Gradient的前世今生_第3张图片
从REINFORCE到PPO,看Policy Gradient的前世今生_第4张图片
从REINFORCE到PPO,看Policy Gradient的前世今生_第5张图片
ppo学到的动作非常光滑,效果也很好。就是相对DQN来说,学的速度比较慢。

感谢阅读!

参考文献

  • UC Berkeley 强化学习课程 CS294-112
  • PPO算法原文 Proximal Policy Optimization Algorithms

你可能感兴趣的:(RL)