策略梯度

策略梯度算法

假设我们在一场游戏里把换进的输出s和智能体的动作a全部组合起来,称作一个轨迹:
$$
\tau={s_1,a_1,s_2,a_2,…,s_t,a_t}
$$
假设智能体参数为$\theta$,我们可以计算某个轨迹$\tau$ 发生的概率为:
$$
\begin{aligned}
p_\theta(\tau)&=p(s_1)p_\theta(a_1\vert s_1)p(s_2\vert s_1,a_1)p_\theta(a2\vert s_2)p(s_3\vert s_2,a_2)\\
&=p(s_1)\prod_{t=1}^Tp_\theta(a_t\vert s_t)p(s_{t+1}\vert s_t,a_t)
\end{aligned}
$$
我们先计算环境输出 s1 的概率 p(s1),再计算根据 s1 执行 a1 的概率 pθ (a1|s1) ,pθ (a1|s1) 是由agent策略里面的网络参数 θ 所决定的。策略网络的输出是一个分布,agent根据这个分布进行采样,决定实际要采取的动 作。接下来环境根据 a1 与 s1 产生 s2,因为 s2 与 s1 是有关系的。

在一个轨迹里,我们把所有的奖励r都加起来,就得到了$R(\tau)$,其代表某一轨迹的奖励。那我们所要做的就是调整agent内部网络的参数$\theta$,使$R(\tau)$的值越大越好。但是实际上$R(\tau)$并不只是一个标量(scalar),它是一个随机变量,因为agent在给定同样的状态下会采取什么样的动作,这是有随机性的。环境在给定同样的观测时要采取什么样的动作,要产生什么样的观测,本身也是有随机性的,所以 $R(\tau)$ 是一个随机变量。我们能够计算的是 $R(\tau)$ 的期望值。 给定某一组参数 θ,我们可计算$R_\theta$ 的期望值为:
$$
\bar R_\theta=\sum_\tau R(\tau)p_\theta(\tau)
$$
要调整θ以求上式最大值,我们可以采用bp算法,先对上式做梯度运算:
$$
\frac{\partial \bar R_\theta}{\partial \theta}=\sum_\tau R(\tau)\frac{\partial p_\theta(\tau)}{\partial \theta}
$$

$$
\frac{\partial p_\theta(\tau)}{\partial \theta}=p_\theta(\tau)\frac{\partial \log p_\theta(\tau)}{\partial \theta}
$$

可得:
$$
\frac{\nabla p_\theta(\tau)}{p_\theta(\tau)}=\nabla\log p_\theta(\tau)
$$
如此:

49it3.png

根据大数定理由采样值更新上式,可得:

49A4T.png

其中:

49hc2.png

那么参数$\theta$更新公式为:
$$
\theta \leftarrow \theta+\beta \nabla \bar R_\theta
$$

策略梯度算法技巧

添加基线

​ 如果给定状态 s 采取动作 a,整场游戏得到正的奖励,就要增加 (s, a) 的概率。如果给定状态 s 执行动作 a,整场游戏得到负的奖励,就要减小 (s, a) 的概率。但在很多游戏里面,奖励总是正的,最低都是 0。比如打乒乓球游戏,分数为 0 ~ 21 分,所以 R(τ ) 总是正的。假设在训练的时候告诉模型,不管是什么动作,都应该要把它的概率提升。虽然 R(τ ) 总是正的,但它的值是有大有小的,比如我们在玩乒乓球游戏时,得到的奖励总是正的,但采取某些动作可能得到 0 分,采取某些动作可能得到 20 分,我们不能提高所有(s,a)的概率。

​ 而且实际上,我们是在做采样,而本来这边应该是一个期望(expectation),对所有可能的 s 与 a 的对进行求和。但我们真正在学习的时候,只是采样了少量的 s 与 a 的对。因为我们做的是采样,所以有一些动作可能从来都没有被采样到。比如在某一个状态,虽然可以执行的动 作有 a、b、c,但我们可能只采样到动作 b 或者只采样到动作 c,没有采样到动作 a。但现在所有动作的奖励都是正的,所以根据上式,在这个状态采取 a、b、c 的概率都应该要提高。我们会遇到的问题是, 因为 a 没有被采样到,所以其他动作的概率如果都要提高,a 的概率就要下降。所以 a 不一定是一个不好 的动作,它只是没有被采样到。但因为 a 没有被采样到,它的概率就会下降,这显然是有问题的。要怎么 解决这个问题呢?我们会希望奖励不总是正的。

​ 为了解决奖励总是正的的问题,我们可以把奖励减 b,即:

494NM.png

​ 其中,b 称为基线。通过这种方法,我们就可以让$R(\tau)$− b 这一项有正有负。如果我们得到的总奖励 $R(\tau)$ > b,就让 (s, a) 的概率上升。如果 $R(\tau)$ < b,就算 R(τ ) 是正的,值很小也是不好的,我们就让 (s, a) 的概率下降,让这个状态采取这个动作的分数下降。b 怎么设置呢?我们可以对$\tau$ 的值取期望,计算 $\tau$ 的平均值,令

b ≈ E[$R(\tau)$]。所以在训练的时候,我们会不断地把$R(\tau)$ 的值记录下来,会不断地计算$R(\tau)$ 的平均值,把这个平均值当作 b 来使用。这样就可以让我们在训练的时候,$R(\tau)$ − b 是有正有负的。

分配合适的分数

494NM.png

在上式中,只要在同一个回合里,所有的状态-动作对就会使用同样的奖励项$R(\tau)$ − b进行加权,这显然是不公平的,因为在同一场游戏里面,也许有些动作是好的,有些动作是不好的。假设整场游戏的结果是好的,但并不代表这场游戏里面每一个动作都是好的。若是整场游戏结果不好,但并不代表游戏里面的每一个动作都是不好的。所以我们希望可以给每一个不同的动作前面都乘上不同的权重。每一个动作 的不同权重反映了每一个动作到底是好的还是不好的。

在理想的状况下,如果我们的采样数据够多,就可以解决这个问题。因为假设我们的采样 数据够多,(sb, a2) 被采样到很多。某一场游戏里,在 sb 执行 a2,我们会得到 +3 分。但在另外一场游戏里,在 sb 执行 a2,我们却得到了 −7 分。但实际上往往我们的采样数据不够充分,此时就需要我们给每一个状态动作对分配合理的分数,要让大家知道它合理的贡献。

一个做法是计算某个状态-动作对的奖励的时候,不把整场游戏得到的奖励全部加起来,只计算从这 个动作执行以后得到的奖励。因为这场游戏在执行这个动作之前发生的事情是与执行这个动作是没有关系 的,所以在执行这个动作之前得到的奖励都不能算是这个动作的贡献。我们把执行这个动作以后发生的所有奖励加起来,才是这个动作真正的贡献:

4955g.png

原来的权重是整场游戏的奖励的总和,现在改成从某个时刻 t 开始,假设这个动作是在 t 开始执行的,从 t 一直到游戏结束所有奖励的总和才能代表这个动作的好坏。

接下来更进一步,我们把未来的奖励做一个折扣,即:

49Wa1.png

虽然在某一时刻,执行某一个动作,会影响接下来所有的结果 (有可能在某一时刻执行的动作,接下来得到的奖励都是这个动作的功劳),但在一般的情况下,时间拖得 越长,该动作的影响力就越小

REINFORCE:蒙特卡洛策略梯度

REINFORCE 用的是回 合更新的方式,它在代码上的处理上是先获取每个步骤的奖励,然后计算每个步骤的未来总奖励 Gt,将 每个 Gt 代入:

49CQt.png

490cO.png

策略梯度预测每一个状态下应该要输出的动作的概率,即输入状态 st,输出动作 at 的概率,比如 0.02、0.08、0.9。实际上输出给环境的动作是随机选择一个动作,比如我们选择向右这个动作,它的one-hot向量就是(0,0,1)。我们把神经网络的输出和实际动作代入交叉熵的公式就可以求出 输出动作的概率和实际动作的概率之间的差距。但实际的动作 at 只是我们输出的真实的动作,它不一定是正确的动作,它不能像手写数字识别一样作为一个正确的标签来指导神经网络朝着正确的方向更新,所以我们需要乘一个奖励回报 Gt。Gt 相当于对真实动作的评价。如果 Gt 越大,未来总奖励越大,那就说 明当前输出的真实的动作就越好,损失就越需要重视。如果 Gt 越小,那就说明动作 at 不是很好,损失的权重就要小一点儿,优化力度也要小一点儿

下图所示为 REINFORCE 算法示意,首先我们需要一个策略模型来输出动作概率,输出动作概 率后,通过 sample() 函数得到一个具体的动作,与环境交互后,我们可以得到整个回合的数据。得到回合数据之后,我们再去执行**learn() 函数,在learn() **函数里面,我们就可以用这些数据去构造损失函 数,“扔”给优化器优化,更新我们的策略模型。

49YZA.png