You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
6.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Policy Gradient
## Policy Gradient的核心思想
`Policy Gradient`的核心思想非常简单,就是找一个函数$$\pi$$,这个函数$$\pi$$能够根据现在环境的状态(state)来产生接下来要采取的行动或者动作(action)。即$$\pi(state)\rightarrow action$$。
函数$$\pi$$其实可以看成是一个模型,那么想在无数次尝试中寻找出能让`Agent`尽量拿高分的模型应该怎样来找呢?我相信你应该猜到了!没错!就是神经网络!
我们可以将游戏画面传给神经网络作为输入,然后神经网络预测一下当前游戏画面下,下一步动作的概率分布。
<div align=center><img src="../img/1004.jpg", height=250/></div>
细心的你可能会发现,如果每次取概率最高的动作作为下一步的动作,那不就成分类了么。其实`Policy Gradient`的并不是每次都选取概率最高的动作,而是根据动作的概率分布进行采样。也就是说就算我预测出来的向上挪的概率为`80%`,也不一定会向上挪。
那么为什么采样而不是直接选取概率最大的呢?因为这样很有灵性。可以想象一下,我们和别人下棋的时候,如果一直按照套路来下,那么对手很可能能够猜到我们下一步棋会怎么走,从而占据主动。如果我们时不时地不按套路出牌,但是这种不按套路的动作不会降低太多对于我们能够赢下这一局棋的几率。那么对手很可能会不知所措,主动权就掌握在我们手里。就像《天龙八部》中虚竹大破珍珑棋局时一样,可能有灵性一点,会有意想不到的效果。
<div align=center><img src="../img/1005.jpg", width=150, height=150/></div>
## Policy Gradient 的原理
现在已经知道`Policy Gradient`是通过神经网络来训练模型,该模型需要根据环境状态来预测出下一步动作的概率分布,并根据这个概率分布进行采样,将采样到的动作作为下一步的动作。
那么会有一个灵魂拷问,就是怎样来鉴定我的神经网络是好还是坏呢?很显然,当然是赢的越多越好了!所以我们不妨假设,让计算机玩`10`把乒乓球游戏,那么可能会有这样的一个统计结果。
<div align=center><img src="../img/1006.jpg", height=350/></div>
那么怎样评价这`10`把游戏打的好还是不好呢?也很明显,将`10`把游戏的所有反馈全部都加起来就好了。如果把这些反馈的和称为总反馈(总得分),那么就有**总反馈(总得分)=第1把反馈1+第1把反馈2+...+第10把反馈m**。也就是说总反馈越高越好。
说到这,有一个问题需要弄清楚:假设总共玩了`100`把,每`10`把计算一次总反馈,那么这`10`次的总反馈会不会是一模一样的呢?其实仔细想想会发现不会一摸一样,因为:
- 游戏的状态实时在变,所以环境状态不可能一直是一样的。
- 动作是从一个概率分布中采样出来的。
既然总反馈一直会变,则可以尝试换一种思路,即计算总反馈的期望,即总反馈的期望越高越好。那这个期望怎么算呢?
首先我们可以将每一把游戏看成一个游戏序列(**状态1->动作1->反馈1->状态2->动作2->反馈2 ... 状态N->动作N->反馈N**)。那么每一个游戏序列(即每一把游戏)的**反馈=反馈1+反馈2+...+反馈N**。因此,若假设$$R(\tau)$$表示游戏序列$$\tau$$的反馈,则有:$$R(\tau)=\sum_{n=1}^N\tau_n$$。
如果把整个乒乓球游戏所有可能出现的状态,动作,反馈组合起来看成是玩了`N`(`N`很大很大) 把游戏,就会有`N`个游戏序列(**游戏序列1游戏序列2游戏序列3, ... , 游戏序列N**)。那么我们在玩游戏时所得到的游戏序列实际上就是从这`N`个游戏序列中采样得到的。
所以游戏的总的反馈期望$$\overline{R_\theta}$$可表示为:$$\overline{R_\theta}=\sum_\tau R(\tau)P(\tau|\theta)$$。这个公式看起来复杂,其实不难理解。
<div align=center><img src="../img/1007.jpg", height=150/></div>
假设我们玩了`10`把游戏,就相当于得到了`10`个游戏序列[$$\tau_1, \tau_2, ..., \tau_{10}$$]。这`10`个游戏序列就相当于从`P`中采样了`10`次$$\tau$$。所以总反馈期望$$\overline{R_\theta}$$又可以近似的表示为:
<center>
$$
\overline{R_\theta} \approx \frac{1}{N}\sum_{n=1}^NR(\tau^n)
$$
</center>
<br>
由于$$\overline{R_\theta}$$的值越大越好,所以我们可以使用梯度上升的方式来更新$$\theta$$。所以就有如下数学推导:
<div align=center><img src="../img/1008.jpg", height=300/></div>
又由于:
<center>
$$
\overline{R_\theta} = \sum_\tau R(\tau)P(\tau|\theta) \approx \frac{1}{N}\sum_{n=1}^NR(\tau^n)
$$
</center>
<br>
所以就有:
<center>
$$
\nabla \overline{R_\theta} \approx \frac{1}{N}\sum_{n=1}^NR(\tau^n) \nabla logP(\tau^n|\theta)
$$
</center>
<br>
你会发现$$\sum_{n=1}^NR(\tau^n)$$很好算,只要把反馈全部加起来就完事了,难算的是$$\nabla logP(\tau^n|\theta)$$。所以我们来看一下$$\nabla logP(\tau^n|\theta)$$应该怎么算。
由于一个游戏序列$$\tau$$是由多个状态,动作,反馈构成的,即:
<center>
$$
\tau=\{s_1, a_1, r_1, s_2, a_2, r_2, ..., s_T, a_T, r_T\}
$$
</center>
<br>
所以:
<center>
$$
P(\tau|\theta)=P(s_1)P(a_1|s_1,\theta)P(r_1,s_2|s_1,a_1)P(a_2|s_2,\theta)P(r_2,s_3|s_2,a_2)...
$$
</center>
<br>
稍微整理一下可知:
<center>
$$
P(\tau|\theta)=P(s_1)\prod_{t=1}^TP(a_t|s_t,\theta)P(\tau_t,s_{t+1}|s_t,a_t)
$$
</center>
<br>
然后两边取$$log$$会得到:
<center>
$$
logP(\tau|\theta)=\sum_{t=1}^T\nabla logP(a_t|s_t,\theta)
$$
</center>
<br>
$$P(a_t|s_t,\theta)$$其实就是神经网络根据环境状态预测出来的下一步的动作概率分布。
<div align=center><img src="../img/1009.jpg", height=150/></div>
到这里,`Policy Gradient`的数学推导全部推导完毕了。我们不妨用一张图来总结一下`Policy Gradient`的算法流程。流程如下:
<div align=center><img src="../img/1010.jpg", height=300/></div>