获取更多内容,请访问博主的个人博客 爱吃猫的小鱼干的Blog
一 广义优势函数估计(GAE)
在VPG中,我们用的 r ( τ ) r(\tau) r(τ)的均值来指引策略的更新,这是个环境给出的“客观”的值;而在AC算法中,我们企图用A_{w}(s, a)来指引梯度更新,但根据算法的设计,这个所谓的A_{w}(s, a)完全是用我们的神经网络算出来的,是“主观的”而不是“客观的”。如果我们算出的A_{w}(s, a)与真实值相差较远,那么对于训练策略网络就完全不能使得策略朝着更好的方向改变,我们的算法自然也无法取得好的结果。VPG的缺点在于,虽然 r ( τ ) r(\tau) r(τ)是个“客观”的值,但是其均值的方差太大。AC的主要思想是引入一定的估计偏差而减少估计的方差,但如果偏差太大了,效果会比VPG还要差。所以说,训练AC的第一个关键之处就在于如何能够更加精确地估计“优势”A_{w}(s, a)、减少估计的偏差。
Shulman提出了广义优势函数估计(generalized advantage estimation,简称GAE),可以相对平衡地控制好估计的偏差与方差,实现误差的最小化。其公式如下:
A
^
t
G
A
E
(
γ
,
λ
)
:
=
(
1
−
λ
)
(
A
^
t
(
1
)
+
λ
A
^
t
(
2
)
+
λ
2
A
^
t
(
3
)
+
…
)
=
(
1
−
λ
)
(
δ
t
V
+
λ
(
δ
t
V
+
γ
δ
t
+
1
V
)
+
λ
2
(
δ
t
V
+
γ
δ
t
+
1
V
+
γ
2
δ
t
+
2
V
)
+
…
)
=
(
1
−
λ
)
(
δ
t
V
(
1
+
λ
+
λ
2
+
…
)
+
γ
δ
t
+
1
V
(
λ
+
λ
2
+
λ
3
+
…
)
+
γ
2
δ
t
+
2
V
(
λ
2
+
λ
3
+
λ
4
+
…
)
+
…
)
=
(
1
−
λ
)
(
δ
t
V
(
1
1
−
λ
)
+
γ
δ
t
+
1
V
(
λ
1
−
λ
)
+
γ
2
δ
t
+
2
V
(
λ
2
1
−
λ
)
+
…
)
=
∑
l
=
0
∞
(
γ
λ
)
l
δ
t
+
l
V
\begin{aligned} \hat{A}_{t}^{\mathrm{GAE}(\gamma, \lambda)} &:=(1-\lambda)\left(\hat{A}_{t}^{(1)}+\lambda \hat{A}_{t}^{(2)}+\lambda^{2} \hat{A}_{t}^{(3)}+\ldots\right) \\ &=(1-\lambda)\left(\delta_{t}^{V}+\lambda\left(\delta_{t}^{V}+\gamma \delta_{t+1}^{V}\right)+\lambda^{2}\left(\delta_{t}^{V}+\gamma \delta_{t+1}^{V}+\gamma^{2} \delta_{t+2}^{V}\right)+\ldots\right) \\ &=(1-\lambda)\left(\delta_{t}^{V}\left(1+\lambda+\lambda^{2}+\ldots\right)+\gamma \delta_{t+1}^{V}\left(\lambda+\lambda^{2}+\lambda^{3}+\ldots\right)\right.\\ &\left.\quad+\gamma^{2} \delta_{t+2}^{V}\left(\lambda^{2}+\lambda^{3}+\lambda^{4}+\ldots\right)+\ldots\right) \\ &=(1-\lambda)\left(\delta_{t}^{V}\left(\frac{1}{1-\lambda}\right)+\gamma \delta_{t+1}^{V}\left(\frac{\lambda}{1-\lambda}\right)+\gamma^{2} \delta_{t+2}^{V}\left(\frac{\lambda^{2}}{1-\lambda}\right)+\ldots\right) \\ &=\sum_{l=0}^{\infty}(\gamma \lambda)^{l} \delta_{t+l}^{V} \end{aligned}
A^tGAE(γ,λ):=(1−λ)(A^t(1)+λA^t(2)+λ2A^t(3)+…)=(1−λ)(δtV+λ(δtV+γδt+1V)+λ2(δtV+γδt+1V+γ2δt+2V)+…)=(1−λ)(δtV(1+λ+λ2+…)+γδt+1V(λ+λ2+λ3+…)+γ2δt+2V(λ2+λ3+λ4+…)+…)=(1−λ)(δtV(1−λ1)+γδt+1V(1−λλ)+γ2δt+2V(1−λλ2)+…)=l=0∑∞(γλ)lδt+lV
表达式中的
λ
\lambda
λ取值在0到1之间,代表这我们对于方差与偏差的取舍。它也是一个“衰减因子”。
一般情况下,训练刚开始的时候,我们的Critic效果较差,即其估计出的 V π ( s ) V_{\pi}(s) Vπ(s)会与现实情况有较大的偏差。此时,应该将 λ \lambda λ设计得比较大。简单地说,当我们“主观”的估计不准的时候,我们应该用更多“客观”的数据去估计 A π A_{\pi} Aπ的;而当训练已经经历了较多个iteration之后,Critic的偏差比较小,则可以将 λ \lambda λ适当降低。
要注意的是,GAE方法还有一个缺点,那就是我们要用到的训练集单位不再只是一步数据 ( s , a , r , s ′ ) \left(s, a, r, s^{\prime}\right) (s,a,r,s′),而是要用到连续多步的数据。这一定程度上会使得训练的灵活性下降。我们说过,VPG方法是一个“回合更新”的算法,训练集的基本单位是一条完整的轨道;而Actor-Critic则是一个“单步更新”的算法,训练集的基本单位是一个transition ( s , a , r , s ′ ) \left(s, a, r, s^{\prime}\right) (s,a,r,s′)。如果采用GAE,则相当于是一种“介于回合更新与单步更新之间的算法”,其训练集的基本单位也是介于一条完整轨道与一步之间。
二控制两个网络的训练步调
在AC中,我们要同时训练Actor与Critic。那么,这二者的节奏应该如何控制?从上节AC的伪代码中看,二者的训练似乎是交替进行的。但是在现实中这样的训练方式真的有效吗?
在随机初始化参数之后而开始训练之前,Critic对于“价值” V π ( s ) V_{\pi}(s) Vπ(s)的误差是极其差的(就相当于是“瞎猜”),如果用它算出来的 A π ( s , a ) A_{\pi}(s,a) Aπ(s,a)来指导Actor的更新,这就好像是“盲人骑瞎马”,难以使得策略取得提升。
在深度学习邻域,同时训练两个神经网络的另一个经典例子是生成问题中的GAN。生成问题的目标是建立一个Generator网络,使之可以生成“看起来像是真的”的图片。但是由于我们没有一个能够衡量“像不像真的”的函数,无法训练Generator,所以我们必须训练另一个网络Discriminator,来作为衡量“真假”的函数,并用它来指引Generator。在训练GAN的时候,Generator的梯度完全是由Discriminator给出的。而Discriminator则可以根据“客观的数据”与Generator的“表现”来进行训练……两个网络之间的关系、与“客观环境”之间的关系和AC算法非常类似(Generator类似于Actor,Discriminator类似于Critic)。如果Discriminator在“瞎指挥”,无法让Generator“学有所成”,这和AC是一个道理。
由于以上的原因,人们一般会对Discriminator进行“预训练”,即初始化两个网络之后先让Generator生成一系列图片(此时的图片类似于噪音)。将这些图片与真实的图片混在一起,让Discriminator先独自进行充分的学习。在“预训练”之后,Discriminator并不见得已经“火眼金睛”,但是它至少已经具有初步的判断力,能够把那种马赛克般的“噪音图片”给判断为假。然后,我们就可以让这个具备了“入门级”的辨识能力的Discriminator指导Generator进行初步的训练,至少要学会不要再生成那种一看起来就是假的“噪音图片”。
在训练中,我们一般交替地训练两者。训练N步Discriminator,再训练M步的Generator。在训练的初期,Discriminator的“判断能力”较低,如果它为Generator指引了错误的方向,则Generator训练再多步也毫无用处。所以训练的初期,我们会让N大于M(常见的操作是取N=5,M=1),让“老师”能够比“学生”更快地成长;不过要注意的是,对于我们“生成以假乱真的图片”这个目标而言,Generator才是解决问题的核心,也是问题中真正的难点。因此,当Discriminator已经相对比较强大的时候,我们要更加重视对Generator的训练。所以,随着训练的深入,我们让N逐渐增大而让M逐渐减少。到训练的末期,我们或许会让M大于N,这是因为Discriminator是一个输入是高维而输出是一个数的网络,而Generator则是一个输入是高维输出也是高维的网络,显然后者需要比前者更多的训练。当Discriminator拥有辨识真假的能力之后,Generator需要更加“勤学苦练”才能达成目标。
要注意的是,不能认为既然Discriminator是用来指导Generator的,所以它可以任意地强。在基础版的GAN中,如果Discriminator比Generator强大太多,则Generator训练的时候会面临梯度消失的问题。我们可以通俗地理解,Discriminator和Generator之间不但存在着“指导”的关系,也同时存在着“竞争”的关系。如果Discriminator比较强大,则与它对抗能够使得Generator快速成长;而如果Discriminator过于强大,使得Generator与其差距太大,则这种悬殊的对抗可能没办法帮助Discriminator成长。
在GAN中之所以Discriminator不宜比Generator强大太多,主要的原因是Generator使用了KL散度作为优化的目标。而当Discriminator太强的时候,KL散度会趋近于0,使得Generator没有梯度继而无法更新。事实上,在GAN的改进版本WGAN中,我们将Generator的优化目标改成推土机距离(Earth Move距离)之后,上述的问题就得到了解决。即使Discriminator很强大,也不会使得Generator无法更新。控制二者训练的步调不过是出于效率的考虑,减少无意义的训练。所以,不应该采取“与太强大的对手对抗不利于成长”这种语言去描述GAN的训练。
在AC算法中,Critic的作用是估计 A π A_{\pi} Aπ并指导Actor的训练。从算法的机制上来说,Critic对于 A π A_{\pi} Aπ的估计非常精确,当然不会对Actor的训练有什么负面效果。控制训练的步调主要考虑的无疑还是效率问题。当策略 π \pi π更新的时候, A π A_{\pi} Aπ自然也会被更新,之前估计出的结果即使再精确后面也用不上,所以我们对于 A π A_{\pi} Aπ的估计也不需要太过于精确,这样可以节约计算成本。在策略迭代算法中,我们说过策略提升这一步中我们可以只进行一定步数雅克比迭代,不必估计得太精确。在AC中也是同样的道理。
总的来说,训练AC的时候绝不能简单地“每训练一步Critic就训练一步Actor”,而应该有意识地控制两个网络训练的步调,例如先训练N步Critic,再训练M步的Actor。在训练初期先将N设的比较大,并让其随着训练深入逐渐减少。具体的训练步调如何掌握,还需要结合具体问题进行具体分析,并进行大量的调试。但是,拥有一个“协调两个网络的训练步调”的意识是极其重要的。
获取更多内容,请访问博主的个人博客 爱吃猫的小鱼干的Blog