Create 从REINFORCE到PPO.md

This commit is contained in:
Johnny He
2018-11-08 08:15:49 +08:00
committed by GitHub
parent f754e98461
commit bef51f32a9
+108
View File
@@ -0,0 +1,108 @@
从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(θ)
θ∗=argmaxθ⁡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(τ)=∑tr(st,at)pθ(τ)=p(s1)∏tπθ(at|st)p(st+1|st,at)
注意,这里的ττ和tt的含义不同,ττ是样本轨迹,tt是样本轨迹上的时间。仔细看pθ(τ)pθ(τ)我们就会发现,将概率展开以后实际上我们的策略可以影响的只有πθ(at|st)πθ(at|st),也就是在状态stst下采取动作atat的概率。这也就是我们策略的数学表示。
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θ(τ)∇θlogpθ(τ)r(τ)dτ=Eτ∼pθ(τ)∇θlogpθ(τ)r(τ)
这里用到了一个小技巧,∇θpθ(τ)=pθ(τ)∇θpθ(τ)pθ(τ)=pθ(τ)∇θlogpθ(τ)∇θpθ(τ)=pθ(τ)∇θpθ(τ)pθ(τ)=pθ(τ)∇θlog⁡pθ(τ),这样做的目的是把pθ(τ)pθ(τ)重新拿到外边来,就可以再写成期望的形式了。
现在公式中的自变量仍然是ττ,实际应用中我们不可能直接对ττ求导,因此我们再把pθ(τ)pθ(τ)带进来看看能不能将ττ给替换为我们可以操作的stst、atat,
∇θ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)]
∇θlogpθ(τ)=∇θlogp(s1)⏟0+∑t[∇θlog⁡πθ(at|st)+∇θlogp(st+1|st,at)⏟0]=∑t∇θlog⁡πθ(at|st)∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlog⁡πθ(at|st)][∑tr(st,at)]
于是,我们也就得到了我们的第一个算法REINFORCE:
用参数为θθ的策略πθ(a|s)πθ(a|s)采样N条样本轨迹τiτi
估计梯度∇θJ(θ)≈1N∑i(∑t∇θlogπθ(at|st))(∑tr(st,at))∇θJ(θ)≈1N∑i(∑t∇θlog⁡πθ(at|st))(∑tr(st,at))
更新参数θ←θ+α∇θJ(θ)θ←θ+α∇θJ(θ),重复1
可以将∇θJ(θ)∇θJ(θ)看成这样的两部分:∑tlogπθ(at|st)∑tlog⁡πθ(at|st)是改进策略的方向,∑tr(st,at)∑tr(st,at)是改进策略的步长,回报大的就走一大步,回报小的就走一小步,回报为负就往反方向走一步。
Actor-Critic
REINFORCE方法缺点很多,它的效率是非常低的,其中一个非常重要的原因就是方差非常大。∑tr(st,at)∑tr(st,at)是每一次仿真的结果,如果效果好了就会对这一次仿真的所有决策奖励,效果不好了就会全部惩罚,这显然是有问题的。
让我们再来好好看一下∇θJ(θ)∇θJ(θ)的计算过程
∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlogπθ(at|st)][∑t=0∞r(st,at)]
∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlog⁡πθ(at|st)][∑t=0∞r(st,at)]
如果t2>t1t2>t1,πθ(at2|st2)πθ(at2|st2)理论上是不会对∑t1t=0r(st,at)∑t=0t1r(st,at)产生影响的。因此上面的计算式可以改进成为
∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlogπθ(at|st)∑t=t∞r(st,at)]
∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlog⁡πθ(at|st)∑t=t∞r(st,at)]
实际上,Qt=∑∞t=tr(st,at)Qt=∑t=t∞r(st′,at′)和我们对Q因子的定义非常接近了,都是从时刻tt开始到结束时的收益。
我们已经减少了一些方差了,能不能再减小呢?我们都知道,对于随机变量XX,其方差DX=EX2(EX)2DX=EX2(EX)2,如果EX2EX2比较小的话,那么方差就会小了。自然想到给r(τ)r(τ)减去一个值,即r(τ)←r(τ)−br(τ)←r(τ)b,选择合适的bb(比如1N∑ir(τi)1N∑ir(τi)),那么方差就会变小了。方差小了,结果会不会变呢?答案是不变的,我们来证明一下:
E[∇θlogπθ(τ)b]=∫πθ(τ)∇θlogπθ(τ)bdτ=∫∇θπθ(τ)bdτ=b∫∇θπθ(τ)dτ=b∇θ∫πθ(τ)dτ=b∇θ1=0
E[∇θlog⁡πθ(τ)b]=∫πθ(τ)∇θlog⁡πθ(τ)bdτ=∫∇θπθ(τ)bdτ=b∫∇θπθ(τ)dτ=b∇θ∫πθ(τ)dτ=b∇θ1=0
所以只要bb本身是与ττ无关的,那么我们就可以这样做!上面的证明是以ττ为自变量的,其实当我们用QtQt时一样可以推出这个结果。
bb的选取成为了另一个问题。理论上可以推出一个最优的bb,不过应用中我们会用VtVt估计bb。也就是说用另外的一个网络来估计Q(st,at)Q(st,at)V(st)=Eat∼πθ(at|st)Q(st,at)V(st)=Eat∼πθ(at|st)Q(st,at),这样就有
∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlogπθ(at|st)[Q(st,at)V(st)])]
∇θJ(θ)=Eτ∼pθ(τ)[∑t∇θlog⁡πθ(at|st)[Q(st,at)V(st)])]
是不是看上去舒服多了?对DQN熟悉的小朋友们就可以用上熟悉的值网络了,不过这次我们的目的是通过估计值网络来帮助更新策略网络。
Q(st,at)V(st)Q(st,at)V(st)实际上就是我们的优势函数A(st,at)A(st,at)。对于连续动作的问题,Q(st,at)Q(st,at)是比较难用网络表示的,即使表示出来也难以由Q(st,at)Q(st,at)直接求出V(st)V(st)。因此,有时候我们会选择直接估计V(st)V(st),用r(st,at)+V(st+1)V(st)r(st,at)+V(st+1)V(st)来估计A(st,at)A(st,at)。注意,这里又是估计的量,r(st,at)+V(st+1)V(st)r(st,at)+V(st+1)V(st)和A(st,at)A(st,at)之间是有偏的。自从我们选择了用估计的Q(st,at)Q(st,at)代替∑∞t=tr(st,at)∑t=t∞r(st′,at′)开始,我们就一直在牺牲偏差来降低方差,以提高我们的学习速度。
Actor-Critic是一个算法框架,这里给出其中一种的算法流程:
用参数为θθ的策略πθ(a|s)πθ(a|s)采样N个状态转移{si,ai,ri,si}{si,ai,ri,si}
更新值网络参数ϕϕ使得Vϕ(si)←ri+Vϕ(si)Vϕ(si)←ri+Vϕ(si)
估计A^(si,ai)=ri+V(si)V(si)A^(si,ai)=ri+V(si)V(si)
估计梯度∇θJ(θ)≈1N∑i∇θlogπθ(ai|si)A^(si,ai)∇θJ(θ)≈1N∑i∇θlog⁡πθ(ai|si)A^(si,ai)
更新参数θ←θ+α∇θJ(θ)θ←θ+α∇θJ(θ),重复1
除了用值函数来估计A^(s,a)A^(s,a)Actor-Critic框架中至少还可以使用以下形式(我们基本上都讨论过了):
∑∞t=0rt∑t=0∞rt —— 轨迹的总回报
∑∞t′=trt′∑t′=t∞rt′ —— 动作后的回报
∑∞t=trt′−b(st)∑t=t∞rt′−b(st) —— 减去基线
Qπ(st,at)Qπ(st,at) —— 状态-行为值函数
Aπ(st,at)Aπ(st,at) —— 优势函数
rt+Vπ(st+1)Vπ(st)rt+Vπ(st+1)Vπ(st) —— 时序差分误差(TD error)
PPO
截至目前,上述提到的算法都还有一些共同的问题。其中一个非常大的问题就是参数空间的距离并不等于策略空间的距离,也就是说在不同的状态下改变相同步长的网络参数,产生策略的概率改变是不同的,而且差异非常大!以下图为例,一个最简单的sigmoid函数输出在同样的参数步长下的输出是变化很大的!
再换句话说,我们希望可以找到一种方法,来自动调整参数空间的步长,以达到策略空间均匀变化的目的。
为了达到这样一个目标,我们需要知道不同的两个策略其目标函数的差异有多少,如果可以有效的评价出这个差值,那么我们就可以根据它来调整我们的策略了。幸运的是,两个策略目标函数的差值之间存在着这样一个关系
J(π′)J(π)=Eτ∼π′[∑t=0∞γtAπ(st,at)]
J(π′)J(π)=Eτ∼π′[∑t=0∞γtAπ(st,at)]
这里ππ是参数化的策略πθ(at|st)πθ(at|st),π′π′则是更新后的策略。证明过程这里提示两点,一是 J(π)=Eτ∼π′[∑∞t=0γtrt]J(π)=Eτ∼π′[∑t=0∞γtrt],二是A(st,at)=rt+V(st+1,at+1)V(st,at)A(st,at)=rt+V(st+1,at+1)V(st,at),代入上式即可。
下面的问题是,我们怎么利用上面这个关系呢?请注意,上式的采样是在新的策略π′π′下进行的,但我们还不知道新的策略是什么怎么采样呢,这不是因果矛盾了吗?难道我们要一个一个策略去试选个最好的?当你想在不同的分布下去估计某个期望,那一定绕不开重要性采样(Importance Sampling),不懂的同学请自行百度。
我们引入一个新的概念,叫折扣状态分布,定义是dπ(s)=(1−γ)∑∞t=0γtP(st=s|π)dπ(s)=(1−γ)∑t=0∞γtP(st=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∞γtAπ(st,at)]=11−γEstdπ′,at∼π′[Aπ(st,at)]=11−γEstdπ′,at∼π[π′(at|st)π(at|st)Aπ(st,at)]
这一部分可能比较难理解,我们一步步来解释一下。第一个等号这里做的事情是将轨迹ττ拆开到每一个时间步上来看,然后将P(st=s|π)P(st=s|π)放到了求期望的角标里,也就是说考虑成了在dπ′(s)dπ′(s)这种折扣分布条件下的期望。第二步就是用了重要性采样,解决了我们上面说到的π′π′我们还不知道的问题。
等等!atat是只和ππ有关了,但是stst不还是和π′π′有关吗?是的。但dπ(s)dπ(s)和dπ′(s)dπ′(s)已经很接近了,理论证明如果ππ和π′π′足够接近,那么其评价函数之差将满足
|J(π′)(J(π)+Lπ(π′))|≤CEst[DKL(π′||π)]−−−−−−−−−−−−√
|J(π′)(J(π)+Lπ(π′))|≤CEst[DKL(π′||π)]
Lπ(π′)=11−γEstdπ,at∼π[π′(at|st)π(at|st)Aπ(st,at)]
Lπ(π′)=11−γEstdπ,at∼π[π′(at|st)π(at|st)Aπ(st,at)]
其中 DKL(π′||π)DKL(π′||π)是ππ和π′π′之间的KL散度,用以衡量两个分布之间的距离。现在,所有的分布中就没有需要从π′π′进行采样的了。我们只需要计算一下更新参数后的ππ和π′π′之间的比值已经KL散度,就可以估计两个策略之间的评价函数的差异了。
虽然现在已经很简单了,但DKL(π′||π)DKL(π′||π)这个东西还是有点让我们伤脑筋,毕竟每一次更新参数都要判断一下这个条件是不是满足。为了解决这个问题,又有一系列的方法出现,比如用近似的方法去估计出最优解,再比如将DKL(π′||π)DKL(π′||π)作为惩罚项加入到loss中。但是这些方法实现起来都比较麻烦,就是那种看都不想看一眼的麻烦。
于是,PPO就粉墨登场了。PPO其实就是近似的求解,原文中提到了两种方式来近似,一种是自动调整对KL散度的惩罚因子,一种是用clip的方法巧妙地构造了一个新的目标函数。因为第二种方法用过的都说好,我们重点来介绍一下它。
很简单,原来的方案中下一轮的参数θk+1θk+1满足
θk+1=argmaxθLθk(θ)s.t.DKL(θk+1||θk)<δLθk(θ)=Eτ∼πk∑t=0∞[πθ(at|st)πθk(at|st)Aπθk(st,at)]
θk+1=argmaxθ⁡Lθk(θ)s.t.DKL(θk+1||θk)<δLθk(θ)=Eτ∼πk∑t=0∞[πθ(at|st)πθk(at|st)Aπθk(st,at)]
现在换一种近似的目标函数
θk+1=argmaxθLclipθk(θ)Lclipθk(θ)=Eτ∼πk∑t=0∞[min(rt(θ)Aπθk(st,at),clip(rt(θ),1−ϵ,1+ϵ)Aπθk(st,at))]rt(θ)=πθ(at|st)πθk(at|st)
θk+1=argmaxθ⁡Lθkclip(θ)Lθkclip(θ)=Eτ∼πk∑t=0∞[min(rt(θ)Aπθk(st,at),clip(rt(θ),1−ϵ,1+ϵ)Aπθk(st,at))]rt(θ)=πθ(at|st)πθk(at|st)
不要被公式的长度给吓到,其实就是控制了ππ和π′π′的比值,如果这两个的比值接近那么自然其KL散度也不比较小,反之就剪掉超过的部分,将其比值限制在一个小范围内。这里的ϵϵ常取0.1或0.2。原文中还做了对比实验,说明了不同目标函数之间的关系。读图我们可以看到当ϵϵ取得很小时,Lclipθk(θ)Lθkclip(θ)和Lθk(θ)DKL(theta||thetak)Lθk(θ)DKL(theta||thetak)是很接近的。