文章目录
深度强化学习—基于策略梯度的方法
本篇主要介绍单智能体强化学习——基于策略梯度的方法。
为什么要用策略梯度方法?
前面我们讲了基于值的强化学习算法,最典型的就是DQN算法,那为什么我们还需要基于策略梯度的方法呢?
思考:我们知道DQN最终的网络输出是每一个动作对应的Q值,它反映了在状态s下,执行动作a后,可以获得的长期价值。基于真实的Q值,我们可以获得最优策略。那如果一个智能体的动作空间很大,甚至是连续的,又该怎么处理呢?显然,很难输出每一个动作的Q值,所以我们考虑直接用一个神经网络来拟合我的策略函数,但是,这里又会有一个问题,基于值函数的方法,通过TD算法来逐渐逼近最优Q值,那基于策略的方法,又该怎么更新它的网络呢?这里就需要用到策略梯度定理,我们根据策略梯度定理来更新策略网络的参数,后面我们会详细讲到。
策略梯度方法的优势
我们刚才提到,用神经网络学习一个策略,可以用来解决连续动作空间的问题,除此之外,在多智能体博弈和部分观测的一些例子中,我们也可以看到策略网络的一些优势,比如在石头剪刀布这样的游戏中,我们的最优策略是什么呢?当然是出石头、剪刀、布的概率都是
1
3
\frac{1}{3}
31,那基于值的方法能得到这样一个策略表示吗?基于值的方法的策略是怎么得到的?通过
ξ
−
g
r
e
e
d
y
\xi-greedy
ξ−greedy得到最终的策略对吧?通过
ξ
−
g
r
e
e
d
y
\xi-greedy
ξ−greedy表示的策略,可以表示每一个动作的概率都是
1
3
\frac{1}{3}
31吗?显然不行,所以我们可以看到基于策略的方法的另一个优势:能够表示更多的策略分布。
在后面的介绍中,我们还是将重点聚焦于离散动作空间,这样的话我们就可以采用和值函数相同的网络结构来表示策略网络,策略网络输出在状态s下对每一个动作的偏好
l
(
s
,
a
)
l(s,a)
l(s,a),然后通过$softmax $函数进行处理:
π
(
a
∣
s
;
ϕ
)
=
e
l
(
s
,
a
;
ϕ
)
∑
a
′
∈
A
e
l
(
s
,
a
′
;
ϕ
)
\pi(a|s;\phi)=\frac{e^{l(s,a;\phi)}}{\sum_{a'\in A}e^{l(s,a';\phi)}}
π(a∣s;ϕ)=∑a′∈Ael(s,a′;ϕ)el(s,a;ϕ)
注意:这里的l(s,a)和Q(s,a)的区别,前者表示了策略网络的输出,表明了策略在状态s下对动作的偏好,并没有表示长期的一个价值。而后者主要表示了在状态s下采取动作,会获得怎样的长期的回报,它表示的是一种长期的价值,二者的区别通过他们的更新方式来体现。l(s,a)通过策略梯度的方式来更新,通过梯度上升来改善策略,而Q(s,a)通过TD算法中的那个迭代公式来个更新。
策略梯度定理
当我们用神经网络来表示一个策略的时候,输出就是对每一个动作的偏好或是一个连续动作,输入是状态,那怎么去更新策略网络的参数呢?首先我们需要定义一个目标函数,一个好的策略的目标是获得更高的预期回报,我们这里记为
J
(
ϕ
)
J(\phi)
J(ϕ),所以现在目标就变为了通过调整策略网络的参数
ϕ
\phi
ϕ,最大化目标函数
J
(
ϕ
)
J(\phi)
J(ϕ),如何最大化呢?
就需要用到梯度更新的方法:
ϕ
=
ϕ
+
α
∇
ϕ
J
(
ϕ
)
\phi = \phi + \alpha \nabla_{\phi}J(\phi)
ϕ=ϕ+α∇ϕJ(ϕ),这里的梯度就表示调整
ϕ
\phi
ϕ使得目标函数变大的方向,那么问题来了,如何求
∇
ϕ
J
(
ϕ
)
\nabla_{\phi}J(\phi)
∇ϕJ(ϕ)呢?这就需要用到策略梯度定理。
策略梯度定理:
∇
ϕ
J
(
ϕ
)
∝
∑
s
∈
S
P
r
(
s
∣
π
)
∑
a
∈
A
Q
π
(
s
,
a
)
∇
ϕ
π
(
a
∣
s
;
ϕ
)
\nabla_{\phi}J(\phi) \propto \sum_{s\in S}Pr(s|\pi)\sum_{a\in A}Q^{\pi} (s,a)\nabla_{\phi} \pi(a|s;\phi)
∇ϕJ(ϕ)∝∑s∈SPr(s∣π)∑a∈AQπ(s,a)∇ϕπ(a∣s;ϕ)
但是,这样一个式子,也并不好求,首先是
P
r
(
s
∣
π
)
Pr(s|\pi)
Pr(s∣π),它表示了在策略
π
\pi
π下,访问状态s的分布,这里可以通过期望的形式去掉这里的第一项求和,然后第二项中,同乘同除以一个
π
(
a
∣
s
;
ϕ
)
\pi(a|s;\phi)
π(a∣s;ϕ),就会发现第二项求和是针对动作a的,我们根据对动作a的加权求和可以直接对后面的求期望,上述过程如下图所示,(由于打公式麻烦,所以直接文字表述):
这里我们再来看倒数第一个公式和倒数第二个公式,现在我们求梯度就变得简单了,虽然这里是求期望,但是我们也可以用样本的值来得到,这种方法叫做随机梯度,已经被证明了可以收敛,只不过迭代过程的稳定性损失了。也就是说,我们可以通过采集到的样本数据,来计算梯度。
接下来我们再来看:
这里的
∇
ϕ
π
(
a
∣
s
;
ϕ
)
\nabla_{\phi} \pi(a|s;\phi)
∇ϕπ(a∣s;ϕ)表示了
ϕ
\phi
ϕ让
π
(
a
∣
s
)
\pi(a|s)
π(a∣s)增大的方向,
Q
π
(
s
,
a
)
Q^{\pi}(s,a)
Qπ(s,a)表示了在该策略下,在状态s下采取动作a的价值,如果价值较高,就让
π
(
a
∣
s
)
\pi(a|s)
π(a∣s)增大的步长大一点,如果价值较低,就让增大的少一点,但是这种情况下,也就是说,在状态s下,采取每一个动作的概率都在增大,只不过相对值不一样,所以这里加入了一个分母,从而只对比相对值,当然,这里的分母还有一个作用,就是刚开始的时候,在状态s下,采取动作a的价值较高,而且对应的概率也高,那通过这个公式,在下一次迭代中,就会让在状态s下采集动作a的概率更高,但是如果这里有价值更高的动作,但是由于采集的概率低,导致对动作价值评估不准也比较低,这样的动作就很难再被更新到高概率,所以,这里分母的加入有效缓解了这样的问题。
一般我们使用下面的公式来计算策略梯度:
∇
J
(
ϕ
)
=
E
a
∼
π
(
.
∣
s
;
ϕ
)
[
Q
π
(
s
,
a
)
∇
log
π
(
a
∣
s
;
ϕ
)
]
\nabla J(\phi)=E_{a\sim\pi(.|s;\phi)}[Q^{\pi}(s,a)\nabla \log \pi(a|s;\phi)]
∇J(ϕ)=Ea∼π(.∣s;ϕ)[Qπ(s,a)∇logπ(a∣s;ϕ)]
但是这里依然存在问题,如果要计算策略梯度的话,我们可以用上面的公式,但是上面的公式中,刚开始的时候对于每一个动作的价值估计从哪儿来呢,而且,我们还要保证这个动作价值估计是针对当前策略的,如果策略发生改变,那之前的动作价值就不能准确评估动作的价值了,第一种方法就是蒙特卡洛方法,在当前策略下疯狂采样,然后求均值来近似这里的动作价值函数,这也就是REINFORCE算法的思想。
这里还需要注意的一点是:我们在计算策略梯度的时候,最后一项表示的是对当前策略的梯度求对数,用的是当前策略!!!也就是说,你每次更新的时候,都需要用当前策略来求梯度,所以之前用其他策略采集的经验就不能用了,如果用的话,就会导致动作价值评估的并不准确。即需要更新的策略和采集经验的策略是同一个策略,也就是我们说的on-policy算法。
如果我们用其他策略采集的经验会发生什么呢?首先,Q值的估计不是针对当前策略的估计,所以这一项会出现问题,其次,在过去策略和当前策略下,对状态s的访问分布不一样。所以必须要用当前策略来采集经验。
REINFORCE
REINFORCE是一各非常经典的基于策略梯度的方法,它根据
∇
J
(
ϕ
)
=
E
a
∼
π
(
.
∣
s
;
ϕ
)
[
Q
π
(
s
,
a
)
∇
log
π
(
a
∣
s
;
ϕ
)
]
\nabla J(\phi)=E_{a\sim\pi(.|s;\phi)}[Q^{\pi}(s,a)\nabla \log \pi(a|s;\phi)]
∇J(ϕ)=Ea∼π(.∣s;ϕ)[Qπ(s,a)∇logπ(a∣s;ϕ)]来计算梯度,但是前面说了,在策略
π
\pi
π下估计动作价值函数本身就不是一件容易的事,在REINFORCE中,采用蒙特卡洛采样的方式来估计当前策略的动作价值函数,具体更新公式如下:
这里我们将需要最大会的回报值前面加了一个负号,就变成最小化了。上面这个公式的意思是每一个回合都会得到每一个状态动作价值的采样值,运行多个回合后,将其平均,就可以用来估计该策略下的动作价值函数,但是,一般用很多个回合的数据就更新一下策略参数,然后将这些数据抛弃,导致更新效率非常低,所以在REINFORCE中,用一个回合的数据来估计动作价值函数,伪代码如下:
现在思考:只用一个回合的数据来估计当前策略的动作价值函数,有没有问题呢?有!高方差,有些状态可能都没有访问到,举个例子,你面前有十张彩票,你只刮一张,得到10000元,你就说,这些彩票的均值就是10000,得到0元,你就说彩票均值就是0元,很明显不合理。
为了缓解REINFORCE高方差的问题,引入了一个基线,这个基线就是状态价值函数
V
(
s
)
V(s)
V(s),引入这个基线之后,并不会改变策略梯度的计算,具体推导过程见下图:
加入基线之后,REINFORCE的损失函数就变为:
这里还存在一个问题:当我们加入基线之后,确实是降低了方差,但是,这是建立在已知V的前提下,但是V的值又该怎么得到呢,V和策略$\pi$是挂钩的,也通过历史数据来拟合的话,不一样引入了方差吗?这里没有准确估计V的情况下,怎么表示偏好呢?这是强化学习的一个核心问题,就算没有准确的估计V,但是基线的加入一般都会降低方差,不需要太准确的V,除此之外,在训练初期,V的估计不准确,却也会护理探索。(有些牵强啊)
Actor-Critic
在REINFORCE中,我们通过策略梯度来更新策略网络的参数,在更新之前,我们需要通过蒙特卡洛算法来采样,通过样本来估计动作价值函数或状态价值函数(有无基线),这种方法只能在回合结束时更新一次,而且方差很高,那有没有其他的方法呢?有!我们之前提到过时序差分算法,和蒙特卡洛算法不同的是,它通过时序差分的方式来更新。
这里写下时序差分的一般形式:
Q
(
s
,
a
)
←
Q
(
s
,
a
)
+
α
(
ξ
−
Q
(
s
,
a
)
)
Q(s,a)\gets Q(s,a) + \alpha(\xi - Q(s,a))
Q(s,a)←Q(s,a)+α(ξ−Q(s,a))这里的
ξ
\xi
ξ表示更新的目标,这其实就是TD形式的动态规划,比如SARSA单步时序差分就是
ξ
=
R
(
s
t
,
a
t
)
+
γ
Q
(
s
t
+
1
,
a
t
+
1
)
\xi = R(s_t,a_t)+\gamma Q(s_{t+1},a_{t+1})
ξ=R(st,at)+γQ(st+1,at+1),这里的
ξ
\xi
ξ不同,更新方式也不同,如果是
ξ
=
R
(
s
t
,
a
t
)
+
γ
R
(
s
t
+
1
,
a
t
+
1
)
+
γ
2
Q
(
s
t
+
2
,
a
t
+
2
)
\xi=R(s_t,a_t)+\gamma R(s_{t+1},a_{t+1})+\gamma ^2 Q(s_{t+2},a_{t+2})
ξ=R(st,at)+γR(st+1,at+1)+γ2Q(st+2,at+2),就表示两步时序差分更新,通过单步更新,Q值的逼近速度也会更快,相较于蒙特卡洛方法,这种方法的方差更低,但是偏差会变高,方差变低是因为只采取一步随机要比一整个回合随机方差要小,偏差更高是因为后面的Q值可能在刚开始的时候并不准确,导致偏差,这里会涉及到方差和偏差的一种折中。
这幅图展示了N步TD算法中方差和偏差随着步数N的变化趋势。
基于上述讨论,我们知道可以用时序差分算法来代替蒙特卡洛方法来估计Q值或V值,所以就提出了actor-critic框架,其中actor网络就用之前的策略梯度进行更新,只不过原来的取最大值加上负号之后变为求最小值,critic网络通过时序差分算法来更新Q或V值,进而再利用Q值来计算策略梯度,更新actor网络。
注意:critic网络使用的也是当前策略采集的经验,因为它的目标是估计当前策略下的Q或V值
A2C:Advantage Actor-Critic
经过上面的铺垫,A2C算法就很好理解了,在A2C算法中,使用一个优势函数
A
d
v
(
s
,
a
)
=
Q
(
s
,
a
)
−
V
(
s
)
Adv(s,a)=Q(s,a)-V(s)
Adv(s,a)=Q(s,a)−V(s)来衡量在当前状态下采取动作a的优势,如果
A
d
v
(
s
,
a
)
>
0
Adv(s,a)>0
Adv(s,a)>0,则说明在状态s下采取动作a是有优势的,反之是没有优势的,反而会降低预期回报,所以我们需要将优势值大于0的动作的概率变高,优势值小于0的动作的概率降低。
所以actor网络的目标函数为:
L
(
ϕ
)
=
−
A
d
v
(
s
t
,
a
t
)
log
π
(
a
t
∣
s
t
;
ϕ
)
L(\phi)=-Adv(s_t,a_t) \log \pi(a_t|s_t;\phi)
L(ϕ)=−Adv(st,at)logπ(at∣st;ϕ),策略梯度为:
∇
ϕ
L
(
ϕ
)
=
−
∇
log
π
(
a
t
∣
s
t
;
ϕ
)
∗
A
d
v
(
s
t
,
a
t
)
\nabla_{\phi}L(\phi)=-\nabla \log \pi(a_t|s_t;\phi) * Adv(s_t,a_t)
∇ϕL(ϕ)=−∇logπ(at∣st;ϕ)∗Adv(st,at)
critic网络用来计算优势函数,但是需要注意的一点是,我们知道
A
d
v
(
s
,
a
)
=
Q
(
s
,
a
)
−
V
(
s
)
Adv(s,a)=Q(s,a)-V(s)
Adv(s,a)=Q(s,a)−V(s),又因为
Q
(
s
,
a
)
=
r
+
γ
V
(
s
t
+
1
)
Q(s,a)=r+\gamma V(s_t+1)
Q(s,a)=r+γV(st+1),所以,我们只需要利用critic网络去拟合V就行了。
critic网络的目标函数:
L
(
θ
)
=
[
(
y
t
−
V
(
s
t
;
θ
)
]
2
L(\theta)=[(y^t-V(s^t;\theta)]^2
L(θ)=[(yt−V(st;θ)]2.
除此之外,在原A2C算法中,还用到了熵正则化的方法,将
−
H
(
π
(
a
∣
s
;
ϕ
)
)
=
π
(
a
∣
s
;
ϕ
)
log
π
(
a
∣
s
;
ϕ
)
-H(\pi(a|s;\phi))=\pi(a|s;\phi) \log \pi(a|s;\phi)
−H(π(a∣s;ϕ))=π(a∣s;ϕ)logπ(a∣s;ϕ)也加入到actor网络的损失函数中,目的是鼓励策略网络进行探索,不要刚开始就收敛到局部最优上。
下面提供简化的A2C伪代码:
PPO
现在我们再来考虑一个问题,随着actor-critic框架的提出,我们知道策略网络的参数更新从一个episode一次变为一步一次,这样会带来一个问题,不能保证每一步的更新都是朝着预期回报增大的方向去的,所以提出了TRPO算法,但由于TRPO计算复杂度高,之后又提出了PPO算法,该算法利用重要性采样,在很多任务上表现很好,因为该算法十分重要,后面将会单独进行分析,这里只贴出PPO算法的优化目标和伪代码。
PPO算法优化目标:
L
(
ϕ
)
=
−
min
(
ρ
(
s
t
,
a
t
)
A
d
v
(
s
t
,
a
t
)
,
c
l
i
p
(
ρ
(
s
t
,
a
t
)
,
1
−
ξ
,
1
+
ξ
)
A
d
v
(
s
t
,
a
t
)
)
L(\phi)=-\min (\rho(s_t,a_t)Adv(s_t,a_t),clip(\rho(s_t,a_t),1-\xi,1+\xi)Adv(s_t,a_t))
L(ϕ)=−min(ρ(st,at)Adv(st,at),clip(ρ(st,at),1−ξ,1+ξ)Adv(st,at))
这里的
ρ
(
s
t
,
a
t
)
=
π
(
a
∣
s
;
ϕ
)
π
β
(
a
∣
s
)
\rho(s_t,a_t)= \frac{\pi(a|s;\phi)}{\pi_{\beta}(a|s)}
ρ(st,at)=πβ(a∣s)π(a∣s;ϕ),分母表示采样的策略。
伪代码:
总结
这篇文章是对强化学习中基于策略梯度方法的一个总结和推导。