fix some errors and add new chapters

This commit is contained in:
qiwang067
2020-07-15 21:13:50 +08:00
parent c05637f761
commit 4a15e865da
214 changed files with 1378 additions and 891 deletions

View File

@@ -12,15 +12,17 @@
- bilibili[李宏毅《深度强化学习》](https://www.bilibili.com/video/BV1MW411w79n)
## 目录
- [P1 策略梯度](https://datawhalechina.github.io/leedeeprl-notes/#/chapter1/chapter1)
- [P2 近端策略优化 (PPO) 算](https://datawhalechina.github.io/leedeeprl-notes/#/chapter2/chapter2)
- [P3 Q 学习 (基本概念)](https://datawhalechina.github.io/leedeeprl-notes/#/chapter3/chapter3)
- [P4 Q 学习 (进阶技巧)](https://datawhalechina.github.io/leedeeprl-notes/#/chapter4/chapter4)
- [P5 Q 学习 (连续动作)](https://datawhalechina.github.io/leedeeprl-notes/#/chapter5/chapter5)
- [P6 演员-评论员算法](https://datawhalechina.github.io/leedeeprl-notes/#/chapter6/chapter6)
- [P7 稀疏奖励](https://datawhalechina.github.io/leedeeprl-notes/#/chapter7/chapter7)
- [P8 模仿学习](https://datawhalechina.github.io/leedeeprl-notes/#/chapter8/chapter8)
- [P9 深度确定性策略梯度 (DDPG) 算法](https://datawhalechina.github.io/leedeeprl-notes/#/chapter9/chapter9)
- [P1 强化学习基础](https://datawhalechina.github.io/leedeeprl-notes/#/chapter1/chapter1)
- [P2 表格型方](https://datawhalechina.github.io/leedeeprl-notes/#/chapter2/chapter2)
- [P3 策略梯度](https://datawhalechina.github.io/leedeeprl-notes/#/chapter3/chapter3)
- [P4 近端策略优化 (PPO) 算法](https://datawhalechina.github.io/leedeeprl-notes/#/chapter4/chapter4)
- [P5 Q 学习 (基本概念)](https://datawhalechina.github.io/leedeeprl-notes/#/chapter5/chapter5)
- [P6 Q 学习 (进阶技巧)](https://datawhalechina.github.io/leedeeprl-notes/#/chapter6/chapter6)
- [P7 Q 学习 (连续动作)](https://datawhalechina.github.io/leedeeprl-notes/#/chapter7/chapter7)
- [P8 演员-评论员算法](https://datawhalechina.github.io/leedeeprl-notes/#/chapter8/chapter8)
- [P9 稀疏奖励](https://datawhalechina.github.io/leedeeprl-notes/#/chapter9/chapter9)
- [P10 模仿学习](https://datawhalechina.github.io/leedeeprl-notes/#/chapter10/chapter10)
- [P11 深度确定性策略梯度 (DDPG) 算法](https://datawhalechina.github.io/leedeeprl-notes/#/chapter11/chapter11)
## 主要贡献者

View File

@@ -1,19 +1,15 @@
- 目录
- [P1 策略梯度](chapter1/chapter1.md)
- [P2 近端策略优化 (PPO) 算](chapter2/chapter2.md)
- [P3 Q 学习 (基本概念)](chapter3/chapter3.md)
- [P4 Q 学习 (进阶技巧)](chapter4/chapter4.md)
- [P5 Q 学习 (连续动作)](chapter5/chapter5.md)
- [P6 演员-评论员算法](chapter6/chapter6.md)
- [P7 稀疏奖励](chapter7/chapter7.md)
- [P8 模仿学习](chapter8/chapter8.md)
- [P9 深度确定性策略梯度 (DDPG) 算法](chapter9/chapter9.md)
- [P1 强化学习基础](chapter1/chapter1)
- [P2 表格型方](chapter2/chapter2)
- [P3 策略梯度](chapter3/chapter3)
- [P4 近端策略优化 (PPO) 算法](chapter4/chapter4)
- [P5 Q 学习 (基本概念)](chapter5/chapter5)
- [P6 Q 学习 (进阶技巧)](chapter6/chapter6)
- [P7 Q 学习 (连续动作)](chapter7/chapter7)
- [P8 演员-评论员算法](chapter8/chapter8)
- [P9 稀疏奖励](chapter9/chapter9)
- [P10 模仿学习](chapter10/chapter10)
- [P11 深度确定性策略梯度 (DDPG) 算法](chapter11/chapter11)

View File

@@ -1,240 +1,308 @@
# Policy Gradient
## Policy Gradient
[toc]
# Reinforement Learning
## Reinforcement Learning
![](img/1.1.png)
在 reinforcement learning 中有 3 个components一个`actor`,一个`environment`,一个`reward function`
让机器玩 video game 时,
* actor 做的事情就是去操控游戏的摇杆, 比如说向左、向右、开火等操作;
* environment 就是游戏的主机, 负责控制游戏的画面负责控制说,怪物要怎么移动, 你现在要看到什么画面等等;
* reward function 就是当你做什么事情,发生什么状况的时候,你可以得到多少分数, 比如说杀一只怪兽得到 20 分等等。
同样的概念用在围棋上也是一样的,
* actor 就是 alpha Go它要决定下哪一个位置
* environment 就是对手;
* reward function 就是按照围棋的规则, 赢就是得一分,输就是负一分等等。
在 reinforcement learning 里面environment 跟 reward function 不是你可以控制的environment 跟 reward function 是在开始学习之前,就已经事先给定的。你唯一能做的事情是调整 actor 里面的 policy使得 actor 可以得到最大的 reward。Actor 里面会有一个 policy 这个policy 决定了actor 的行为。Policy 就是给一个外界的输入,然后它会输出 actor 现在应该要执行的行为。
强化学习讨论的问题是说一个 agent 怎么在一个复杂不确定的环境里面去极大化它能获得的这个奖励。示意图由两部分组成一部分是agent下面一部分是环境。然后在强化学习过程中Agent 跟 environment 其实一直在交互。当 agent 在环境里面获取到状态agent 会利用这个状态会输出一个 action一个决策。然后这个决策会放到这个环境之中去然后环境会通过这个 agent 采取的决策输出下一个状态以及当前的这个决策得到的奖励。Agent 的目的就是为了尽可能多的从环境中获取这个奖励。
![](img/1.2.png)
**Policy 一般写成 $\pi$**。假设你是用 deep learning 的技术来做 reinforcement learning 的话,**policy 就是一个 network**。Network 里面就有一堆参数, 我们用 $\theta$ 来代表 $\pi$ 的参数。Network 的 input 就是现在 machine 看到的东西,如果让 machine 打电玩的话, 那 machine 看到的东西就是游戏的画面。Machine 看到什么东西,会影响你现在 training 到底好不好 train。
举例来说,在玩游戏的时候, 也许你觉得游戏的画面,前后是相关的,也许你觉得说,你应该让你的 policy看从游戏初始到现在这个时间点所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子,你会比较难处理。要让你的 machine你的 policy 看到什么样的画面, 这个是你自己决定的。让你知道说给机器看到什么样的游戏画面可能是比较有效的。Output 的就是今天机器要采取什么样的行为。
我们可以把强化学习跟监督学习做一个对比。上图说的是 supervised learning 举个图片分类的例子,监督学习的意思就是说我们有一大堆标定的数据,比如车、然后飞机、然后凳子这些标定的图片。然后这些图片都要满足 i.i.d 分布,就是它们之间是没有关联的一个分布。然后我们训练一个分类器,比如说右边这个神经网络。为了分出这个图片,车辆是飞机。训练过程中,我们直接把这个真实的 label 给了这个网络。当这个网络做出一个错误的预测,比如现在输入了这个汽车的图片,然后它预测出来是飞机。我们就会直接告诉它,你现在这个预测是错误的,正确的 label 应该是车。然后我们把这个错误写成一个`损失函数(loss function)`,通过 Backpropagation 来训练这个网络。所以在监督学习过程中,有两个假设,
上图就是具体的例子,
* policy 就是一个 network
* input 就是游戏的画面,它通常是由 pixels 所组成的;
* output 就是看看说有那些选项是你可以去执行的output layer 就有几个 neurons。
假设你现在可以做的行为就是有 3 个output layer 就是有 3 个 neurons。每个 neuron 对应到一个可以采取的行为。Input 一个东西后network 就会给每一个可以采取的行为一个分数。接下来,你把这个分数当作是概率。 actor 就是看这个概率的分布,根据这个机率的分布,决定它要采取的行为。比如说 70% 会走 left20% 走 right10% 开火等等。概率分布不同actor 采取的行为就会不一样。
* 输入的数据。标定的数据,它都是没有关联的,尽可能没有关联。因为如果有关联的话,这个网络就是其实不好学习。
* 我们告诉了这个 learner 正确的标签是什么,这样它可以通过正确的标签来修正自己的这个预测。
![](img/1.3.png)
接下来用一个例子来说明 actor 是怎么样跟环境互动的。 首先 actor 会看到一个游戏画面,我们用 $s_1$ 来表示这个游戏画面,它代表游戏初始的画面。接下来 actor 看到这个游戏的初始画面以后,根据它内部的 network根据它内部的 policy 来决定一个 action。假设它现在决定的 action 是向右,它决定完 action 以后,它就会得到一个 reward ,代表它采取这个 action 以后得到的分数
我们把一开始的初始画面,写作 $s_1$ 把第一次执行的动作叫做 $a_1$,把第一次执行动作完以后得到的 reward 叫做 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$这个都可以你自己看得懂就好。Actor 决定一个的行为以后, 就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给 actor这个 actor 决定要开火,然后它可能杀了一只怪,就得到五分。然后这个 process 就反复地持续下去,直到今天走到某一个 timestamp 执行某一个 action得到 reward 之后, 这个 environment 决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。
在强化学习里面,这两点其实都不满足。举一个 Atari Breakout 游戏的例子,这是一个打砖块的游戏,控制木板,然后把这个球反弹到上面来消除这些砖块。在游戏过程中,大家可以发现你这个 agent你这个 learner 得到的观测其实不是个 i.i.d 的分布。就是你上一帧下一帧其实有非常强的这个连续性。另外一点,你这个玩游戏的过程中,其实并没有立刻获得这个反馈,比如你现在把这个木板往右移,那么只会使得这个球然后往上或者往左上去一点,你并不会得到立刻的反馈。所以这也是为什么强化学习这么困难,就是你没有得到很好的反馈,然后你依然希望这个 agent 在这个环境里面学习
![](img/1.4.png)
一场游戏叫做一个 `Episode`。把这个游戏里面,所有得到的 reward 都总合起来,就是 `Total reward`,我们称其为`Return(回报)`,用 R 来表示它。Actor 存在的目的就是想办法去 maximize 它可以得到的 reward。
在强化学习之中,它的训练数据其实就是这样一个玩游戏的过程。你从步数从第一步开始,然后你采取一个决策,比如说你把这个往右移,接到这个球了。第二步你又做出决策,然后你得到的 training data 就是这样一个序列,一个玩游戏的一个序列。比如现在是在第三步,然后你把这个序列放进去,你希望这个网络,这个 learner 可以输出一个决策,在当前的这个状态应该输出往右移或者往左移。这里有个问题就是我们没有标签来说明你现在这个动作是正确还是错误,我们必须等到这个游戏结束可能,这个游戏结束要可能十秒过后才结束。现在这个动作往左往右到底是不是对最后游戏的结束能赢有帮助,其实这是不清楚的的。这里就面临一个`奖励的延迟(Delayed Reward)`,所以就使得训练这个网络非常困难。
![](img/1.5.png)
首先,`environment` 是一个`function`,游戏的主机也可以把它看作是一个 function虽然它不一定是 neural network可能是 rule-based 的规则,但你可以把它看作是一个 function。这个 function一开始就先吐出一个 state也就是游戏的画面接下来你的 actor 看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 environment 把 $a_1$ 当作它的输入,然后它再吐出 $s_2$吐出新的游戏画面。Actor 看到新的游戏画面,再采取新的行为 $a_2$,然后 environment 再看到 $a_2$,再吐出 $s_3$。这个 process 会一直持续下去,直到 environment 觉得说应该要停止为止。
在一场游戏里面,我们把 environment 输出的 $s$ 跟 actor 输出的行为 $a$,把这个 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory`,如下式所示。
$$
\text { Trajectory } \tau=\left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\}
$$
我们对比下强化学习和监督学习。首先强化学习输入的序列的数据并不是像 supervised learning 里面这些样本都是独立的。另外一点是 learner 并没有被告诉你正确的每一步,正确的行为应该是什么。这个 learner 不得不自己去发现哪些行为是可以使得它最后得到这个奖励的啊,通过不停的去尝试发现最有利的 action。
每一个 trajectory你可以计算它发生的概率。假设现在 actor 的参数已经被给定了话,就是 $\theta$。根据 $\theta$,你其实可以计算某一个 trajectory 发生的概率,你可以计算某一个回合,某一个 episode 里面, 发生这样子状况的概率
这里还有一点是 agent 获得自己能力的过程中,其实是通过不断地试错,就这里 trial-and-error explorationexploration 和 exploitation 是强化学习里面非常核心的一个问题。Exploitation意思是说你会去尝试一些新的行为让这些新的行为有可能会使你得到更高的这个奖励也有可能使你一无所有。Exploitation 说的是你就是就采取你已知道可以获得最大行为的过程,那你就重复执行这个 action 就可以了。因为你已经知道可以获得一定的奖励,所以这就需要一个权衡,这也是在这个监督学习里面没有的情况
$$
\begin{aligned}
p_{\theta}(\tau)
&=p\left(s_{1}\right) p_{\theta}\left(a_{1} | s_{1}\right) p\left(s_{2} | s_{1}, a_{1}\right) p_{\theta}\left(a_{2} | s_{2}\right) p\left(s_{3} | s_{2}, a_{2}\right) \cdots \\
&=p\left(s_{1}\right) \prod_{t=1}^{T} p_{\theta}\left(a_{t} | s_{t}\right) p\left(s_{t+1} | s_{t}, a_{t}\right)
\end{aligned}
$$
在强化学习过程中,没有这个非常强的 supervisor这里只有一个奖励信号(reward signal)就是这个环境会在很久以后告诉你之前你采取的行为到底是不是有效的。Agent 在这个强化学习里面学习的话就非常困难,因为你并没有得到即时反馈,当你采取一个行为过后,如果是监督学习,你就立刻可以获得一个指引,就说你现在做出了一个错误的决定,那么正确的决定应该是谁。而在强化学习里面,环境可能会告诉你这个行为是错误,但是它并没有告诉你正确的行为是什么。而且更困难的是,他可能是在一两分钟过后告诉你错误,它在告诉你之前的行为到底行不行。所以这也是强化学习和监督学习不同的地方。
怎么算呢,如上式所示。在假设你 actor 的参数就是 $\theta$ 的情况下,某一个 trajectory $\tau$ 的概率就是这样算的,你先算 environment 输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你 policy 里面的 network 参数 $\theta$ 所决定的, 它是一个概率,因为你的 policy 的 network 的 output 是一个 distributionactor 是根据这个 distribution 去做 sample决定现在实际上要采取的 action是哪一个。接下来 environment 根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟$s_1$ 还是有关系的,下一个游戏画面,跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在 actor 采取的行为 $a_1$,就会产生 $s_2$。
这件事情可能是概率,也可能不是概率,这个取决于 environment就是主机它内部设定是怎样。看今天这个主机在决定要输出什么样的游戏画面的时候有没有概率。因为如果没有概率的话这个游戏的每次的行为都一样你只要找到一条 path 就可以过关了,这样感觉是蛮无聊的 。所以游戏里面,通常是还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。Process 就反复继续下去,你就可以计算一个 trajectory $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。
**这个概率取决于两部分**
* 一部分是 `environment 的行为` environment 的 function 它内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是 environment environment 这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。
* 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$ actor 要采取什么样的 $a_t$ 会取决于你 actor 的参数 $\theta$ 所以这部分是 actor 可以自己控制的。随着 actor 的行为不同,每个同样的 trajectory 它就会有不同的出现的概率。
![](img/1.6.png)
通过跟监督学习比较,我们可以总结出这个强化学习的一些特征。
在 reinforcement learning 里面,除了 environment 跟 actor 以外, 还有`reward function`。Reward function 根据在某一个 state 采取的某一个 action 决定说现在这个行为可以得到多少的分数。 它是一个 function给它 $s_1$$a_1$,它告诉你得到 $r_1$。给它 $s_2$ $a_2$,它告诉你得到 $r_2$。 把所有的 $r$ 都加起来,我们就得到了 $R(\tau)$ ,代表某一个 trajectory $\tau$ 的 reward。在某一场游戏里面 某一个 episode 里面,我们会得到 R。**我们要做的事情就是调整 actor 内部的参数 $\theta$ 使得 R 的值越大越好。** 但实际上 reward 并不只是一个 scalarreward 其实是一个 random variableR 其实是一个 random variable。 因为 actor 在给定同样的 state 会做什么样的行为这件事情是有随机性的。environment 在给定同样的 observation 要采取什么样的 action要产生什么样的 observation本身也是有随机性的。所以 R 是一个 random variable你能够计算的是它的期望值。你能够计算的是说在给定某一组参数 $\theta$ 的情况下,我们会得到的 R 的期望值是多少
$$
\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)
$$
这个期望值的算法如上式所示,穷举所有可能的 trajectory $\tau$ 每一个 trajectory $\tau$ 都有一个概率。比如 $\theta$ 是一个很强的 model 那它都不会死。如果有一个 episode 很快就死掉了, 它的概率就很小;如果有一个 episode 都一直没有死, 那它的概率就很大。根据你的 $\theta$ 你可以算出某一个 trajectory $\tau$ 出现的概率,接下来你计算这个 $\tau$ 的 total reward 是多少。 Total reward weighted by 这个 $\tau$ 出现的概率,对所有的 $\tau$ 进行求和,就是期望值。给定一个参数,你会得到的期望值。
$$
\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=E_{\tau \sim p_{\theta}(\tau)}[R(\tau)]
$$
我们还可以写成上式那样,从 $p_{\theta}(\tau)$ 这个 distribution sample 一个 trajectory $\tau$,然后计算 $R(\tau)$ 的期望值,就是你的 expected reward。 我们要做的事情就是 maximize expected reward。
* 首先它是有这个 trial-and-error exploration它需要通过在环境里面探索来获取对这个环境的理解
* 第二点是这个强化学习 agent 会从环境里面获得延迟的奖励。
* 第三点是这个强化学习的训练过程中时间非常重要,因为你得到的数据都是有这个时间关联的,而不是这个 i.i.d 分布的。大家如果做过机器学习的话就会发现,如果你的观测数据有非常强的关联,其实会使得这个训练非常不稳定。这也是为什么监督学习我们希望我们的 data 尽量是 i.i.d 了,这样就可以消除数据之间的相关性。
* 第四点是这个 agent 的行为会影响它随后得到的数据,这一点其实也是非常重要的。就是在我们训练这个 agent 的过程中,很多时候我们也是通过正在学习的这个 agent 去跟这个环境交互得到数据。所以如果我们在训练过程中,这个 agent 的模型如果快死掉了,那么就会使得我们采集到的数据也是非常糟糕的。这样整个训练过程就失败了。所以其实在强化学习里面一个非常重要的问题就是怎么使得让这个 agent 的行为一直稳定的提升。
![](img/1.7.png)
怎么 maximize expected reward 呢?我们用的是 `gradient ascent`,因为要让它越大越好,所以是 gradient ascent。Gradient ascent 在 update 参数的时候要加。要进行 gradient ascent我们先要计算 expected reward $\bar{R}$ 的 gradient 。我们对 $\bar{R}$ 取一个 gradient这里面只有 $p_{\theta}(\tau)$ 是跟 $\theta$ 有关,所以 gradient 就放在 $p_{\theta}(\tau)$ 这个地方。$R(\tau)$ 这个 reward function 不需要是 differentiable我们也可以解接下来的问题。举例来说如果是在 GAN 里面,$R(\tau)$ 其实是一个 discriminator它就算是没有办法微分也无所谓你还是可以做接下来的运算。
取 gradient之后我们背一个公式
$$
\nabla f(x)=f(x)\nabla \log f(x)
$$
我们可以对 $\nabla p_{\theta}(\tau)$ 使用这个公式,然后会得到 $\nabla p_{\theta}(\tau)=p_{\theta}(\tau) \nabla \log p_{\theta}(\tau)$。
接下来, 分子分母,上下同乘$p_{\theta}(\tau)$,然后我们可以得到下式:
$$
\frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)}=\log p_{\theta}(\tau)
$$
然后如下式所示, 对 $\tau$ 进行求和,把 $R(\tau)$ 和 $\log p_{\theta}(\tau)$ 这两项 weighted by $ p_{\theta}(\tau)$ 既然有 weighted by $p_{\theta}(\tau)$,它们就可以被写成这个 expected 的形式。也就是你从 $p_{\theta}(\tau)$ 这个 distribution 里面 sample $\tau$ 出来, 去计算 $R(\tau)$ 乘上 $\nabla\log p_{\theta}(\tau)$,然后把它对所有可能的 $\tau$ 进行求和,就是这个 expected value 。
$$
\begin{aligned}
\nabla \bar{R}_{\theta}&=\sum_{\tau} R(\tau) \nabla p_{\theta}(\tau)\\&=\sum_{\tau} R(\tau) p_{\theta}(\tau) \frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)} \\&=
\sum_{\tau} R(\tau) p_{\theta}(\tau) \nabla \log p_{\theta}(\tau) \\
&=E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right]
\end{aligned}
$$
实际上这个 expected value 没有办法算,所以你是用 sample 的方式来 sample 一大堆的 $\tau$。你 sample $N$ 笔 $\tau$ 然后你去计算每一笔的这些 value然后把它全部加起来最后你就得到你的 gradient。你就可以去 update 你的参数,你就可以去 update 你的 agent如下式所示。
$$
\begin{aligned}
E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] &\approx \frac{1}{N} \sum_{n=1}^{N} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(\tau^{n}\right) \\
&=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)
\end{aligned}
$$
注意 $p_{\theta}(\tau)$ 里面有两项,$p(s_{t+1}|s_t,a_t)$ 来自于 environment$p_\theta(a_t|s_t)$ 是来自于 agent。 $p(s_{t+1}|s_t,a_t)$ 由环境决定从而与 $\theta$ 无关,因此 $\nabla \log p(s_{t+1}|s_t,a_t) =0 $。因此 $\nabla p_{\theta}(\tau)=
\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$。
你可以非常直观的来理解这个部分,也就是在你 sample 到的 data 里面, 你 sample 到,在某一个 state $s_t$ 要执行某一个 action $a_t$ 这个 $s_t$ 跟 $a_t$ 它是在整个 trajectory $\tau$ 的里面的某一个 state and action 的 pair。
* 假设你在 $s_t$ 执行 $a_t$,最后发现 $\tau$ 的 reward 是正的, 那你就要增加这一项的概率,你就要增加在 $s_t$ 执行 $a_t$ 的概率。
* 反之,在 $s_t$ 执行 $a_t$ 会导致$\tau$ 的 reward 变成负的, 你就要减少这一项的概率。
为什么我们关注这个强化学习,其中非常重要的一点就是强化学习得到的这个模型可以取得超人类的结果。这一个有意思的点就是之前的监督学习就是我们在获取的这些监督数据,其实是让人来标定的。比如说 ImageNet这些图片都是人类标定的。那么我们就可以确定这个算法的 upper bound(上限)。其实就是人类的这个标定结果决定了它永远不可能超越人类。但是对于强化学习,它在环境里面自己探索,有非常大的潜力,它可以获得超越人的能力的这个表现,比如说 AlphaGo谷歌 DeepMind 的 AlphaGo 这样一个强化学习的算法可以把人类最强的棋手都打败。
![](img/1.8.png)
这个怎么实现呢? 你用 gradient ascent 来 update 你的参数,你原来有一个参数 $\theta$ ,把你的 $\theta$ 加上你的 gradient 这一项,那当然前面要有个 learning ratelearning rate 其实也是要调的,你可用 Adam、RMSProp 等方法对其进行调整。
我们可以套下面这个公式来把 gradient 计算出来:
这里我给大家举一些在现实生活中强化学习的一些例子。
$$
\nabla \bar{R}_{\theta}=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)
$$
实际上,要套上面这个公式, 首先你要先收集一大堆的 s 跟 a 的 pair你还要知道这些 s 跟 a 在跟环境互动的时候,你会得到多少的 reward。 这些资料怎么收集呢?你要拿你的 agent它的参数是 $\theta$,去跟环境做互动, 也就是拿你已经 train 好的 agent 先去跟环境玩一下,先去跟那个游戏互动一下, 互动完以后,你就会得到一大堆游戏的纪录,你会记录说,今天先玩了第一场,在第一场游戏里面,我们在 state $s_1$ 采取 action $a_1$,在 state $s_2$ 采取 action $a_2$ 。
* 国际象棋其实也是一个强化学习的过程,因为这个棋手就是在做出一个选择来跟对方对战。
* 然后在自然界中,羚羊其实也是在做一个强化学习,它刚刚出生的时候,可能都不知道怎么站立,然后它通过 trial- and-error 的一个尝试三十分钟过后它就可以每个小时36公里跑到这样的速度很快的适应了这个环境。
玩游戏的时候是有随机性的,所以 agent 本身是有随机性的,在同样 state $s_1$,不是每次都会采取 $a_1$,所以你要记录下来。在 state $s_1^1$ 采取 $a_1^1$,在 state $s_2^1$ 采取 $a_2^1$。整场游戏结束以后,得到的分数是$R(\tau^1)$。你会 sample 到另外一笔 data也就是另外一场游戏。在另外一场游戏里面你在 state $s_1^2$ 采取 $a_1^2$,在 state $s_2^2$ 采取 $a_2^2$,然后你 sample 到的就是 $\tau^2$,得到的 reward 是 $R(\tau^2)$
你就可以把 sample 到的东西代到这个 gradient 的式子里面,把 gradient 算出来。也就是把这边的每一个 s 跟 a 的 pair 拿进来,算一下它的 log probability 。你计算一下在某一个 state 采取某一个 action 的 log probability然后对它取 gradient然后这个 gradient 前面会乘一个 weightweight 就是这场游戏的 reward。 有了这些以后,你就会去 update 你的 model。
Update 完你的 model 以后。你要重新去收集 data再 update model。这边要注意一下一般 policy gradient sample 的 data 就只会用一次。你把这些 data sample 起来,然后拿去 update 参数,这些 data 就丢掉了。接着再重新 sample data才能够去 update 参数, 等一下我们会解决这个问题。
* 你也可以把股票交易看成一个强化学习的问题,就怎么去买卖去使你的收益极大化
* 玩雅达利游戏或者一些电脑游戏,其实也是在一个强化学习的过程。
![](img/1.9.png)
接下来讲一些实现细节。实现方法是这个样子,把它想成一个分类的问题,在 classification 里面就是 input 一个 image然后 output 决定说是 10 个 class 里面的哪一个。在做 classification 时,我们要收集一堆 training data要有 input 跟 output 的 pair
在实现的时候,你就把 state 当作是 classifier 的 input。 你就当在做 image classification 的 problem只是现在的 class 不是说 image 里面有什么 objects。 现在的 class 是说,看到这张 image 我们要采取什么样的行为,每一个行为就是一个 class。比如说第一个 class 叫做向左,第二个 class 叫做向右,第三个 class 叫做开火。
这些训练的数据从哪里来的呢? 做分类的问题时,要有 input 和正确的 output。 这些训练数据是从 sampling 的 process 来的。假设在 sampling 的 process 里面,在某一个 state你 sample 到你要采取 action a 你就把这个 action a 当作是你的 ground truth。你在这个 state你 sample 到要向左。 本来向左这件事概率不一定是最高, 因为你是 sample它不一定概率最高。假设你 sample 到向左,在 training 的时候 你叫告诉 machine 说,调整 network 的参数, 如果看到这个 state你就向左。在一般的 classification 的 problem 里面,其实你在 implement classification 的时候, 你的 objective function 都会写成 minimize cross entropy其实 minimize cross entropy 就是 maximize log likelihood。
上图是强化学习的一个经典例子,就是在雅达利叫 Pong 的一个游戏。这个游戏就是通过把这个球然后拍到左边,然后左边这个选手需要把这个球拍到右边,这里我给大家看的是训练好的一个 agent 。大家可以猜猜哪一边是强化学习的 agent 。右边是强化学习的agent 。你会发现它,一直在做这种无意义的一些振动,而正常的选手不会出现这种这样的行为
![](img/1.10.png)
做 classification 的时候objective function 就是 maximize 或 minimize 的对象, 因为我们现在是 maximize likelihood 所以其实是 maximize 你要 maximize 的对象,如下式所示:
$$
\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)
$$
像这种 loss function。你可在 TensorFlow 里 call 现成的 function它就会自动帮你算。
然后你就可以把 gradient 计算出来这是一般的分类问题。RL 唯一不同的地方是 loss 前面乘上一个 weight这个是整场游戏的时候得到的 total reward R 它并不是在 state s 采取 action a 的时候得到的 reward。 你要把你的每一笔 training data都 weighted by 这个 R。然后你用 TensorFlow 或 PyTorch 去帮你算 gradient 就结束了,跟一般 classification 差不多。
## Tips
这边有一些在实现的时候,你也许用得上的 tip。
### Tip 1: Add a Baseline
在这个 pong游戏里面,这里的决策其实就是两个动作就是你把它往上或者往下。如果强化学习是通过学习一个 policy network 来分类的话,其实就是输入当前帧的图片,然后 policy network 就会输出所有决策的可能性。
![](img/1.11.png)
在这种情况下面,对于监督学习的话,我们就可以直接告诉这个 agent你正确的 label 是什么。在这种游戏情况下面,我们并不知道它的正确的标签是什么。
第一个 tip 是 add 一个 baseline。add baseline 是什么意思呢?如果 given state s 采取 action a 会给你整场游戏正面的 reward就要增加它的概率。如果 state s 执行 action a整场游戏得到负的 reward就要减少这一项的概率。
但在很多游戏里面, reward 总是正的,就是说最低都是 0。比如说打乒乓球游戏 你的分数就是介于 0 到 21 分之间,所以这个 R 总是正的。假设你直接套用这个式子, 在 training 的时候,告诉 model 说,不管是什么 action 你都应该要把它的概率提升。 在理想上,这么做并不一定会有问题。因为虽然说 R 总是正的,但它正的量总是有大有小,你在玩乒乓球那个游戏里面,得到的 reward 总是正的,但它是介于 0~21分之间有时候你采取某些 action 可能是得到 0 分,采取某些 action 可能是得到 20 分。
![](img/1.12.png)
在强化学习里面,我们是通过让它尝试去玩这个游戏,然后直到游戏结束过后,我们再去说你前面的一系列动作到底是正确还是错误。
假设你有 3 个 action a/b/c 可以执行,在某一个 state 有 3 个 action a/b/c可以执行。根据这个式子你要把这 3 项的概率, log probability 都拉高。 但是它们前面 weight 的这个 R 是不一样的。 R 是有大有小的weight 小的它上升的就少weight 多的,它上升的就大一点。 因为这个 log probability它是一个概率所以action a、b、c 的和要是 0。 所以上升少的,在做完 normalize 以后, 它其实就是下降的,上升的多的,才会上升。
![](img/1.13.png)
然后这个过程就是 rollout 的一个过程。Rollout 的意思是从当前帧去生成很多局的游戏。然后这个很多局就通过是你当前的这个网络去跟这个环境交互,然后你就会得到一堆这个观测。这里其实每一个观测,你就可以把它看成一个轨迹(Trajectory),轨迹的话就是当前当前帧以及它采取的策略,每一步的这个策略都有。最后结束过后,你会知道你到底有没有把这个球击到对方区域,然后对方没有接住,你是赢了还是输了。我们可以通过观测序列以及 Eventual Reward 来训练这个 agent ,使它尽可能地采取最后可以获得这个 Eventual Reward 的过程。
![](img/1.14.png)
其实强化学习是有一定的历史的,只是最近大家把强化学习跟深度学习结合起来,就形成了`深度强化学习(Deep Reinforcemet Learning)`。我这里做一个类比,就是把它类比于这个传统的计算机视觉以及深度计算机视觉。
![1](img/1.13.png)
* 传统的计算机视觉由两个过程组成。你给一张图,我们先要提取它的特征,用一些设计好的 feature比如说 HOG、DPM。提取这些 feature 后,我们再单独训练一个分类器。这些分类器可以是 SVM、Boosting然后就可以分出这个图片到底是狗是猫。
这个是一个理想上的状况,但是实际上,我们是在做 sampling 就本来这边应该是一个 expectation summation over 所有可能的 s 跟 a 的 pair。 但你真正在学的时候,当然不可能是这么做的,你只是 sample 了少量的 s 跟 a 的 pair 而已。 因为我们做的是 sampling有一些 action 可能从来都没有 sample 到。在某一个 state1虽然可以执行的 action 有 a/b/c 3 个,但你可能只 sample 到 action b你可能只 sample 到 action c你没有 sample 到 action a。但现在所有 action 的 reward 都是正的,所以根据这个式子,它的每一项的概率都应该要上升。你会遇到的问题是,因为 a 没有被 sample 到,其它 action 的概率如果都要上升a 的概率就下降。 所以 a 不一定是一个不好的 action 它只是没被 sample 到。但只是因为它没被 sample 到, 它的概率就会下降,这个显然是有问题的,要怎么解决这个问题呢?你会希望你的 reward 不要总是正的。
![1.](img/1.14.png)
为了解决 reward 总是正的这个问题,你可以把 reward 减掉一项叫做 b这项 b 叫做 baseline。你减掉这项 b 以后,就可以让 $R(\tau^n)-b$ 这一项, 有正有负。 所以如果得到的 total reward $R(\tau^n)$ 大于 b 的话,就让它的概率上升。如果这个 total reward 小于 b就算它是正的正的很小也是不好的你就要让这一项的概率下降。 如果$R(\tau^n)<b$ 你就要让这个 state 采取这个 action 的分数下降 。这个 b 怎么设呢?一个最简单的做法就是, 你把 $\tau^n$ 的值取 expectation 算一下 $\tau^n$的平均值。
$$
b \approx E[R(\tau)]
$$
这是其中一种做法, 你可以想想看有没有其它的做法。
所以在 implement training 的时候,你会不断地把 $R(\tau)$ 的分数记录下来 然后你会不断地去计算 $R(\tau)$ 的平均值, 你会把这个平均值,当作你的 b 来用。 这样就可以让你在 training 的时候, $\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$ 乘上前面这一项, 是有正有负的,这个是第一个 tip。
### Tip 2: Assign Suitable Credit
第二个 tip给每一个 action 合适的 credit。什么意思呢如果我们看今天下面这个式子的话
$$
\nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}\left(R\left(\tau^{n}\right)-b\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)
$$
我们原来会做的事情是,在某一个 state假设你执行了某一个 action a它得到的 reward ,它前面乘上的这一项 $R(\tau^n)-b$。
只要在同一个 Episode 里面,在同一场游戏里面, 所有的 state 跟 a 的 pair它都会 weighted by 同样的 reward term这件事情显然是不公平的因为在同一场游戏里面 也许有些 action 是好的,有些 action 是不好的。 假设整场游戏的结果是好的, 并不代表这个游戏里面每一个行为都是对的。若是整场游戏结果不好, 但不代表游戏里面的所有行为都是错的。所以我们希望可以给每一个不同的 action 前面都乘上不同的 weight。每一个 action 的不同 weight 它反映了每一个 action 到底是好还是不好。
* 2012年过后我们有了这个卷积神经网络大家就把特征提取以及分类两者合到一块儿去就是说我们训练一个神经网络。这个神经网络既可以做特征提取也可以做分类。然后它可以实现这种端到端的一个训练然后可以让它里面的参数在每一个阶段都得到极大的优化这样就得到了一个非常重要的突破。
![](img/1.15.png)
举个例子, 假设这个游戏都很短,只有 3~4 个互动, 在 $s_a$ 执行 $a_1$ 得到 5 分。在 $s_b$ 执行 $a_2$ 得到 0 分。在 $s_c$ 执行 $a_3$ 得到 -2 分。 整场游戏下来,你得到 +3 分,那你得到 +3 分 代表在 state $s_b$ 执行 action $a_2$ 是好的吗?并不见得代表 state $s_b$ 执行 $a_2$ 是好的。因为这个正的分数,主要来自于在 state $s_a$ 执行了 $a_1$,跟在 state $s_b$ 执行 $a_2$ 是没有关系的,也许在 state $s_b$ 执行 $a_2$ 反而是不好的, 因为它导致你接下来会进入 state $s_c$,执行 $a_3$ 被扣分,所以整场游戏得到的结果是好的, 并不代表每一个行为都是对的
我们也可以把这个放到强化学习之中去
* 之前的强化学习,比如 TD-Gammon 玩 backgammon 这个游戏,它其实也是通过了这个设计特征,然后通过训练价值函数的一个过程,就是它先设计了很多手工的一些特征,这个手工特征可以描述现在整个状态。得到这些特征过后,它就可以通过训练一个分类网络或者分别训练一个价值估计函数,然后来做出决策。
* 现在我们有了深度学习,有了神经网络,那么就大家也把这个过程改进成一个 end-to-end training 的一个过程。你直接输入这个状态,我们不需要去手工的设计这个特征,就可以让它直接输出 action。那么就可以用一个神经网络来拟合我们这里的 value function 或 policy networ省去 了 feature engineering 的过程。
![](img/1.16.png)
如果按照我们刚才的讲法,整场游戏得到的分数是 3 分,那到时候在 training 的时候, 每一个 state 跟 action 的 pair都会被乘上 +3。 在理想的状况下,这个问题,如果你 sample 够多就可以被解决。因为假设你 sample 够多,在 state $s_b$ 执行 $a_2$ 的这件事情,被 sample 到很多。就某一场游戏,在 state $s_b$ 执行 $a_2$,你会得到 +3 分。 但在另外一场游戏,在 state $s_b$ 执行 $a_2$,你却得到了 -7 分,为什么会得到 -7 分呢? 因为在 state $s_b$ 执行 $a_2$ 之前, 你在 state $s_a$ 执行 $a_2$ 得到 -5 分,-5 分这件事可能也不是在 $s_b$ 执行 $a_2$ 的错,这两件事情,可能是没有关系的,因为它先发生了,这件事才发生,所以它们是没有关系的
为什么强化学习在这几年就用到各种应用中去,比如玩游戏以及机器人的一些应用,然后已经取得了这样可以击败人类最好棋手的一个结果
在 state $s_b$ 执行 $a_2$ 可能造成的问题只有会在接下来 -2 分,而跟前面的 -5 分没有关系的。但是假设我们今天 sample 到这项的次数够多,把所有发生这件事情的情况的分数通通都集合起来, 那可能不是一个问题。但现在的问题就是,我们 sample 的次数是不够多的。在 sample 的次数不够多的情况下,你要给每一个 state 跟 action pair 合理的 credit你要让大家知道它合理的 contribution。怎么给它一个合理的 contribution 呢? 一个做法是计算这个 pair 的 reward 的时候,不把整场游戏得到的 reward 全部加起来,**只计算从这一个 action 执行以后所得到的 reward**。因为这场游戏在执行这个 action 之前发生的事情是跟执行这个 action 是没有关系的, 所以在执行这个 action 之前得到多少 reward 都不能算是这个 action 的功劳。跟这个 action 有关的东西, 只有在执行这个 action 以后发生的所有的 reward 把它加起来,才是这个 action 真正的 contribution。所以在这个例子里面在 state $s_b$ 执行 $a_2$ 这件事情,也许它真正会导致你得到的分数应该是 -2 分而不是 +3 分,因为前面的 +5 分 并不是执行 $a_2$ 的功劳。实际上执行 $a_2$ 以后,到游戏结束前, 你只有被扣 2 分而已,所以它应该是 -2。那一样的道理今天执行 $a_2$ 实际上不应该是扣 7 分,因为前面扣 5 分,跟在 $s_b$ 这个 state 执行 $a_2$ 是没有关系的。在 $s_b$ 这个 state 执行 $a_2$,只会让你被扣两分而已,所以也许在 $s_b$ 这个 state 执行 $a_2$ 你真正会导致的结果只有扣两分而已。如果要把它写成式子的话是什么样子呢?如下式所示。
有几点组成:
* 第一点是我们有了更多的这个计算能力我们有了更多的这个GPU显卡然后可以更快的做更多的这个 trial-and-error 的尝试通。
* 过这种不同尝试就可以使得 agent 在这个环境里面获得很多信息,然后可以在这个环境里面取得很大的奖励。
* 第三点是我们有了这个端到端的一个训练,可以使得这个特征提取跟这个最后的这个价值估计或者决策一块来优化,这样就可以得到了一个更强的一个决策网络。
![](img/1.17.png)
接下来我会给大家再看一些强化学习里面比较有意思的一些例子。
本来的 weight 是整场游戏的 reward 的总和。那现在改成从某个时间 $t$ 开始,假设这个 action 是在 t 这个时间点所执行的,从 $t$ 这个时间点,一直到游戏结束所有 reward 的总和,才真的代表这个 action 是好的还是不好的。
* 第一个例子是DeepMind 研发的一个走路的agent。这个 agent 往前走一步,你就会得到一个 reward。这个agent 有不同的这个形态,然后就可以学到很多有意思的功能。比如怎么跨越这个障碍物,就像那个蜘蛛那样的 agent 。怎么跨越障碍物,像这个人有双腿一样, 这个 agent 往前走。以及像这个人形 的agent怎么在一个曲折的道路上面往前走这个结果也是非常有意思。这个人形 agent 会把手举得非常高,因为它这个手的功能就是为了使它身体保持平衡,这样它就可以更快的在这个环境里面这个往前跑,而且这里你也可以增加这个环境的难度,加入一些扰动,这个 agent 就会变得更鲁棒。
* 第二个例子是机械臂抓取的一个例子。因为这个机械臂的应用自动去强化学习需要大量的这个 rollout所以它这里就有好多机械臂然后一个分布式系统然后可以让这个机械臂尝试抓取不同的物体。你发现这个盘子里面物体的形状、形态其实都是不同的这样就可以让这个机械臂学到一个统一的一个行为。然后在不同的这个抓取物下面都可以采取最优的一个抓取特征。你的这个抓取的物件形态存在很多不同一些传统的这个抓取算法就没法把这些所有物体都抓起来因为你对每一个物体都需要做一个建模这样的话就是非常花时间。但是就通过这个强化学习你就可以学到一个统一的一个抓取算法在不同物体上它都可以适用。
* 第三个例子是 OpenAI 做的一个机械臂翻魔方的一个结果这里它们18年的时候先设计了一个这个手指的一个机械臂让它可以通过翻动手指使得这个手中的这个木块达到一个预定的这个设定。人的手指其实是一个非常精细的过程怎么使得这个机械手臂也具有这样灵活的能力就一直是一个问题。它们就通过这个强化学习在一个虚拟环境里面先训练让 agent 能翻到特定的这个方向,再把它应用到这个真实的手臂之中。这也其实在强化学习里面是一个比较常用的一个做法,就是你先在虚拟环境里面得到一个很好的 agent然后再把它使用到真实的这个机器人中。因为很多时候真实的机械手臂通常都是非常容易坏而且非常贵你没法大批量的购买。2019年的时候让它们进一步改进然后这个手臂就可以玩魔方了。这个结果也是非常有意思的到后面你看这个魔方就被恢复成了个六面都是一样的结构了。
* 第四个例子是一个穿衣服的 agent ,就是训练这个 agent 穿衣服。因为很多时候你要在电影或者一些动画实现这个人穿衣的这种场景,通过手写执行命令让机器人穿衣服其实是非常困难。有很多时候穿衣服也是一个非常精细的一个操作,那么它们这个工作就是通过训练这个强化学习 agent然后就可以实现这个穿衣功能。这里你还可以加入一些扰动然后 agent 可以抗扰动,然后可能有这种 failure case agent 就穿不进去,就卡在这个地方。
## Introduction to Sequential Decision Making
![](img/1.18.png)
**接下来再更进一步,我们把未来的 reward 做一个 discount**,由此得到的回报被称为 `Discounted Return(折扣回报)`。为什么要把未来的 reward 做一个 discount 呢?因为虽然在某一个时间点,执行某一个 action会影响接下来所有的结果有可能在某一个时间点执行的 action接下来得到的 reward 都是这个 action 的功劳。但在比较真实的情况下, 如果时间拖得越长,影响力就越小。 比如说在第二个时间点执行某一个 action 那我在第三个时间点得到的 reward 可能是在第二个时间点执行某个 action 的功劳,但是在 100 个 timestamp 之后,又得到 reward那可能就不是在第二个时间点执行某一个 action 得到的功劳。 所以我们实际上在做的时候,你会在 R 前面乘上一个 `discount factor` $\gamma$ $\gamma \in [0,1] $ ,一般会设个 0.9 或 0.99
接下来我们讲序列决策过程,强化学习研究的问题 是 agent 跟环境交互,这幅图左边画的是一个 agentagent 一直在跟环境进行交互。这个agent 把它输出的动作给环境,然后环境取得这个动作过后,会进行到下一步,然后会把下一步的观测跟它上一步是否得到奖励返还给 agent。通过这样的交互过程然后会产生很多观测agent 的目的就是为了从这些观测之中学到能极大化奖励的策略。
* $\gamma = 0$ : Only care about the immediate reward
* $\gamma = 1$ : Future reward is equal to the immediate reward。
如果 time stamp $t'$ 越大,它前面就乘上越多次的 $\gamma$,就代表说现在在某一个 state $s_t$ 执行某一个 action $a_t$ 的时候,它真正的 credit 是在执行这个 action 之后所有 reward 的总和,而且你还要乘上 $\gamma$。
举一个例子, 你就想成说,这是游戏的第 1、2、3、4 回合,那你在游戏的第二回合的某一个 $s_t$ 你执行 $a_t$,它真正的 credit 得到的分数应该是,假设你这边得到 +1 分 这边得到 +3 分,这边得到 -5 分,它的真正的 credit应该是 1 加上一个 discount 的 credit 叫做 $\gamma$ 乘上 3再加上 $\gamma^2$ 乘上 -5。
如果大家可以接受这样子的话, 实际上就是这么 implement 的。这个 b 可以是 state-dependent 的,事实上 b 它通常是一个 network estimate 出来的,它是一个 network 的 output。
### Rewards
![](img/1.19.png)
奖励是由环境给的一个反馈信号,这个信号指定了这个 agent 在某一步采取了某个策略是否得到奖励。强化学习的目的就是为了极大化 agent 可以获得的奖励,这个 agent 在这个环境里面存在的目的就是为了极大它的期望积累的奖励。
把 $R-b$ 这一项合起来,我们统称为` advantage function``A` 来代表 advantage function。Advantage function 是 dependent on s and a我们就是要计算的是在某一个 state s 采取某一个 action a 的时候advantage function 有多大。
![](img/1.20.png)
个 advantage function 它的上标是 $\theta$ $\theta$ 是什么意思呢? 因为在算 advantage function时你要计算$\sum_{t^{\prime}=t}^{T_{n}} r_{t^{\prime}}^{n}$ ,你会需要有一个 interaction 的结果。你会需要有一个 model 去跟环境做 interaction你才知道你接下来得到的 reward 会有多少。这个 $\theta$ 就是代表说是用 $\theta$ 这个 model 跟环境去做 interaction然后你才计算出这一项。从时间 t 开始到游戏结束为止,所有 R 的 summation 把这一项减掉 b然后这个就叫 advantage function。它的意义就是假设我们在某一个 state $s_t$ 执行某一个 action $a_t$,相较于其他可能的 action它有多好。它真正在意的不是一个绝对的好 而是说在同样的 state 的时候 是采取某一个 action $a_t$ 相较于其它的 action 它有多好,它是相对的好。因为会减掉一个 b减掉一个 baseline 所以这个东西是相对的好,不是绝对的好。 $A^{\theta}\left(s_{t}, a_{t}\right)$ 通常可以是由一个 network estimate 出来的,这个 network 叫做 critic。
里我给大家举一些奖励的例子。不同的环境,奖励的也是不同的。
* 比如说一个下象棋的选手,它的目的其实就为了赢棋,奖励是说在最后棋局结束的时候,他知道会得到一个正奖励或者负奖励。
* 羚羊站立其实也是一个强化学习过程,那它得到的奖励就是它是否可以最后跟它妈妈一块离开或者它被吃掉。
* 股票管理里面,奖励定义由你的股票获取的收益跟损失决定。
* 在玩雅达利游戏的时候,奖励就是你有没有在增加游戏的分数,奖励本身的稀疏程度其实也决定了这个游戏的难度。
### Sequential Decision Making
![](img/1.21.png)
在一个强化学习环境里面agent 目的就是为了选取一系列的动作,从而使得它的奖励可以极大化。所以这些采取的措施必须有长期的影响,但这个过程里面它的奖励其实是被延误了。就是说你现在采取的某一步决策可能要等到时间很久过后才知道这一步到底产生了什么样的影响。这里一个示意图就是我们玩这个 Atari 的 Pong 这个游戏,你可能只有到最后游戏结束过后,你才知道这个球到底有没有击打过去。中间你采取的 up 或 down 行为,并不会直接产生奖励。
强化学习里面一个重要的课题就是在近期奖励和远期奖励的一个 trade-off。怎么让 agent 的取得更多的长期奖励是强化学习的问题。
![](img/1.22.png)
在跟环境的交互过程中agent 其实会获得很多观测。然后在每一个观测会采取一个动作它也会得到一个奖励。Agent在采取当前动作的时候会依赖于它之前得到的这个历史所以你可以把整个游戏的状态看成关于这个历史的函数。
![](img/1.23.png)
在 Agent 自己的内部也有一个函数来更新这个状态。当 agent 的状态跟环境的状态等价的时候,我们就说现在这个环境是 full observability就是全部可以观测。
![](img/1.24.png)
但是有一种情况是 agent 得到的观测并不能包含所有环境运作的状态因为在这个强化学习的设定里面环境的状态才是真正的所有状态。Agent 在玩游戏的过程中,比如说它在玩这个 Black jack 这个游戏,它能看到的其实是牌面上的牌或者在玩雅达利游戏的时候,你们观测到的只是当前电视上面这一帧的信息,你并没有得到游戏内部里面所有的运作状态。所以在这种情况下面,强化学习通常被建模成一个 POMDP 的问题。
### Major Components of an RL Agent
![](img/1.25.png)
对于一个强化学习 agent它有哪些组成成分首先agent 它可能有一个这决策函数policy function这个函数是会被 agent 用来选取它下一步的动作。
然后它也可能生成一个价值函数(value function)。这个价值函数被 agent 用来对现在当前状态进行估价,它就是说你进入现在这个状态,到底可以对你后面的收益带来多大的影响。当这个价值函数大的时候,说明你进入这个状态越有利。
另外一个组成成分是这个模型(model)。这里模型表示了 agent 对这个环境的状态进行了一个整个理解,他决定了这个世界是如何进行的。
### Policy
![](img/1.26.png)
我们深入看这三个组成成分的一些细节。
Policy 就是决定了这个 agent 的行为,它其实是一个函数,把输入的状态变成行为。所以这里有有两种 policy。
* 一种是 stochastic policy它就是这个 $\pi$ 函数,当你输入一个状态 s 的时候它输出其实是一个概率。这概率就是你所有行为的一个概率然后你可以进一步对这个概率分布进行采样然后得到真实的你采取的行为。比如说这个概率可能是有70%的概率往左30%的概率往右,那么你通过采样就可以得到一个 action。
* 另外一种是 deterministic policy就是说你这里有可能只是采取它的极大化采取最有可能的概率。所以你现在这个概率就是事先决定好的。
从 Atari 游戏的来看的话policy function 的输入就是一游戏的一帧,然后它的输出决定你是往左走或者是往右走。
### Value Function
![](img/1.27.png)
价值函数是一个折扣的未来奖励的加和,就是你通过进行某一种行为,然后你未来得到多大的奖励。然后这个价值函数里面其实有一个 discount factor。我们希望尽可能在短的时间里面得到尽可能多的奖励。所以如果我们说十天过后我给你100块钱跟我现在给你100块钱你肯定更希望我现在就给你100块钱因为你可以把这100块钱存在银行里面你就会有一些利息。所以我们就通过把这个 discount factor 放到价值函数的定义里面。后面我们得到的奖励价值函数的定义其实是一个期望。
你可以看这里有一个 $\mathbb{E}_{\pi}$ 的期望,这里有个小角标是 $\pi$ 函数,这个 $\pi$ 函数就是说在我们已知某一个 policy function 的时候,到底可以得到多少的奖励,所以这个价值函数就是把我们后面未来得的奖励。
对于这个奖励函数,我们另外还有一个这个 Q 函数。Q 函数里面包含两个变量有一个是状态另外一个是动作。所以你未来可以获得多少的奖励你可以看到它的这个期望取决于你当前的状态和当前的行为。这个Q 函数是强化学习算法在学习的一个函数。因为当我们得到这个Q 函数的过后,我们进入某一种状态,它最优的行为其实就可以通过这个 Q 函数来得到。
### Model
![](img/1.28.png)
然后这里第三个组成部分是这个模型,模型决定了下一个状态会是什么样的,就是说下一步的状态取决于你当前的状态以及你当前采取的行为。然后它由两个部分组成,一个是 Probability它这个转移状态之间是怎么转移的。另外一个模型的是这个奖励函数当你在当前状态采取了某一个行为可以得到多大的奖励。
![](img/1.29.png)
当我们有了这三个成分过后,然后其实就形成了一个马尔科夫决策过程(Markov Decision Process)。这个决策过程可视化了状态之间的转移以及我们采取的行为。
![](img/1.30.png)
这里我们来看一个走迷宫的例子,这个例子是要求这个 agent 从 start 开始,然后到达 goal 的位置。我们这里设定的奖励是每走一步,你就会得到一个负的奖励,然后这里可以采取的动作是往上下左右走。然后当前状态用现在 agent 所在的位置来描述。
![](img/1.31.png)
我们可以用不同的强化学习算法来解这个环境,如果我们这里采取的是 Policy-based RL。当我们学习好了这个环境过后然后在每一个状态我们就会得到一个最佳的行为。比如说现在在第一格开始的时候我们知道它最佳行为是往右走然后第二格的时候得到的最佳策略是往上走第三格是往右走。通过这个最佳的策略我们就可以最快地到达终点。
![](img/1.32.png)
如果换成 Value-based RL 这个算法,利用价值函数来作为导向,我们就会得到另外一种表征。这里就表征了你每一个状态会返回一个价值,比如说你现在当前在 start 位置的时候,你的价值是 -16因为你最快可以16步到达终点。因为每走一步会减一所以你这里的价值是 -16。当我们快接近最后终点的时候它的这个数字是变得越来越大。在拐角的时候比如要现在在第二格 -15。然后现在 agent 会看上下,他看到上面指变大变成 -14了它下面是 -16那么这个 agent 的肯定就会采取一个往上走的策略。所以通过这个学习的值的不同,我们可以抽取出现在最佳的策略。
### Types of RL Agents
![](img/1.33.png)
所以根据强化学习 agent 的不同,我们可以把 agent 进行归类。
* 基于价值函数的 agent。这一类 agent 显式地学习的就是价值函数,隐式地学习了它的策略。因为这个策略是从我们学到的价值函数里面推算出来的。
* 另外一种基于策略导向的 agent。它直接去学习 policy就是说你直接给它一个 state它就会输出这个动作的概率。然后在这个 policy-based agent 里面并没有去学习它的价值函数。
* 然后另外还有一种 agent 是把这两者结合。把 value-based 和 policy-based 结合起来就有了 `Actor-Critic agent`。这一类 agent 就把它的策略函数和价值函数都学习了,然后通过两者的交互得到一个最佳的行为。
![](img/1.34.png)
另外,我们是可以通过 agent 到底有没有学习这个环境模型来分类。
* 有一类这个强化学习 agent 我们可以叫它 model-based RL agent就是它通过学习这个状态的转移来采取措施。
* 另外一种是 model-free RL agent就是它没有去直接估计这个状态的转移也没有得到环境的具体转移变量然后它通过学习 value function 和 policy function 进行决策。这种 model-free 的模型里面它并没有一个环境转移的一个模型。
![](img/1.35.png)
把几类模型放到同一个 pie chart 里面。三个组成部分value function、policy、model。按一个 agent 具不具有三者中的两者或者一者可以把它分成很多类。
### Exploration and Exploitation
![](img/1.36.png)
在强化学习里面Exploration 和 Exploitation 是两个很核心的问题。
* Exploration 的意思是说我们怎么去探索这个环境。通过尝试不同的行为,然后可以得到一个最佳的策略,得到最大奖励的策略。
* Exploitation 的意思是我们现在不去尝试新的东西,就采取我们已知的可以得到很大奖励的行为。
因为在刚开始的时候这个强化学习 agent 并不知道它采取了某个行为会发生什么,所以它只能通过试错去探索。所以 Exploration 就是在试错来理解采取的这个行为到底可不可以得到好的奖励。Exploitation 是说我们直接采取已知的可以得到很好奖励的行为。所以这里就面临一个 trade-off。怎么通过牺牲一些短期的 reward 来获得行为的理解。
![](img/1.37.png)
这里我再给大家举一些例子来说明 Exploration 和 Exploitation 的定义。
* 比如说我们在选择餐馆的时候。
* Exploitation 的意思是说我们直接去你最喜欢的餐馆吗,因为你去过这个餐馆去过很多次了,所以你知道这里面的菜都非常可口。
* Exploration 就是说你把手机拿出来,你直接搜索一个新的餐馆,然后去尝试它到底好不好吃。这里的结果就是有可能这种新的餐馆非常不满意,那么你就这个钱就浪费了。
* 广告的例子。
* Exploitation 就是说我们直接可以采取最优的这个广告策略。
* Exploration 就是说我们换一种广告方式,然后看这个新的广告策略到底可不可以得到奖励。
* 挖油的例子。
* Exploitation 就是说我们直接在已知的地方挖油。那么我们就可以确保可以挖到油。
* Exploration 就是说我们在一个新的一个地方挖油,就有很大的概率,你可能不能发现任何油,但也可能有比较小的概率可以发现一个非常大的一个油田。
* 玩游戏的例子。
* Exploitation 就是说你总是采取某一种策略。比如说,你可能打街霸,你采取的策略可能是蹲在角落,然后一直触脚。这个策略嗯很可能可以奏效,但是可能遇到特定的对手就失效。
* Exploration 就是说你可能尝试一些新的一些招式,有可能你会发出大招来,这样就可能一招毙命。
### Experiment with Reinforcement Learning
![](img/1.38.png)
接下来我们会进入一个实践环节。强化学习其实是一个理论跟实践结合的一个机器学习分支,需要去推导很多算法公式。然后去理解它算法背后的一些数学原理。另外一方面,上机实践通过实现算法,然后在很多实验环境里面去真正探索这个算法是不是可以得到预期效果也是一个非常重要的一个过程。所以我希望大家把实践提到一个很高的高度,真正去实践这个强化学习的算法。
![](img/1.39.png)
然后我们这门课程,我会在网页上面公布一些代码,会有很多会利用到 Python编程然后也会利用到深度学习的一些包主要是用 PyTorch 为主,然后在[这个链接](https://github.com/cuhkrlcourse/RLexample)里面,我其实已经公布了一些 RL 相关的代码。
![](img/1.40.png)
你就直接调用现有的包来实践,现在其实有很多深度学习的包可以用,熟练使用这里面的两三种其实已经可以实现非常多的功能。所以你并不需要从头去去造轮子,就直接调用它里面的函数去实现你想实现的功能。
![](img/1.41.png)
强化学习的话就不得不提 OpenAI 这家公司。OpenAI 是一个非盈利的人工智能研究公司。Open AI 公布了非常多的学习资源以及这个算法资源,他们之所以叫 Open AI就是他们把他们所有开发的这些算法都 open source 出来。
![](img/1.42.png)
`OpenAI Gym` 里面包含了很多现有的环境,比如说这个 Atari 游戏然后还有一些强化学习里面比较经典的一些控制的环境。Gym Retro 是这个 gym 环境的进一步扩展,包含了更多的一些游戏。
![](img/1.43.png)
强化学习的这个交互就是由 agent 跟环境进行交互。所以我们算法的 interface 也是用这个来表示。比如说我们现在安装了 OpenAI Gym。那我们这里就可以直接调入 Taxi-v2 的环境就建立了一个这个环境初始化这个环境过后就可以进行交互了。Agent 得到这个观测过后,它就会输出一个 action。然后这个 action 会被这个环境拿进去执行这个step然后环境就会往前走一步然后返回新的 observation 和 reward 以及一个 flag variable 就决定你现在这个游戏是不是结束了。这几行代码就实现了强化学习里面的 framework。
![](img/1.44.png)
在OpenAI Gym 里面有很经典的控制类游戏,比如说 Acrobot就是把这个两节铁杖然后甩了立起来。还有 CartPole通过控制一个平板让这个木棍立起来。还有 MountainCar 的一个例子,就通过前后移动这个车,让它到达这个旗子的位置。大家可以去[这个链接](https://gym.openai.com/envs/#classic_control)看一看这些环境。在刚开始测试强化学习的时候,可以选择这些简单环境,因为这些环境可能是在一两分钟之内你就可以见到一个效果。
![](img/1.45.png)
这里我们看一下 CartPole 的这个环境。对于这个环境有两个动作Cart 往左移还是往右移。这里得到了观测它这个车当前的位置Cart 当前的往左往右移的速度,这个杆的这个角度以及它的杆的最高点的这个速度。
如果 observation 越详细的话,就可以更好地描述当前这个所有的状态。然后这里有 reward 定义的话,如果能多保留一步,然后你就会得到一个奖励,所以你尽可能多的时间存活来得到更多的奖励。一段游戏,它的终止条件就是说,你没有把这个杆平衡。当这个杆的角度大于某一个角度的时候或者这个车已经出到外面的时候,你就输了。所以这个 agent 的目的就是为了控制这个木棍,让它尽可能地保持平衡以及尽可能保持在这个环境的中央。
```python
import gym
env = gym.make('CartPole-v0)
env.reset()
env.render() # display the rendered scene
action = env.action_space.sample()
observation, reward, done, info = env.step(action)
```
如果我们玩这个环境的话,就就直接可以 import gym调入 CartPole 这个环境。然后这里就可以通过这个采样,然后来执行这个环境。
## Todo
* Gym 安装过程
* RL例子
## References
* [Intro to Reinforcement Learning (强化学习纲要)](https://github.com/zhoubolei/introRL)
* [神经网络与深度学习](https://nndl.github.io/)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 362 KiB

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 380 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 565 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 672 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 876 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 708 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 509 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 859 KiB

BIN
docs/chapter1/img/1.20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 311 KiB

BIN
docs/chapter1/img/1.21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

BIN
docs/chapter1/img/1.22.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

BIN
docs/chapter1/img/1.23.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

BIN
docs/chapter1/img/1.24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
docs/chapter1/img/1.25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

BIN
docs/chapter1/img/1.26.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

BIN
docs/chapter1/img/1.27.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

BIN
docs/chapter1/img/1.28.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
docs/chapter1/img/1.29.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 458 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 KiB

After

Width:  |  Height:  |  Size: 335 KiB

BIN
docs/chapter1/img/1.30.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

BIN
docs/chapter1/img/1.31.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

BIN
docs/chapter1/img/1.32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
docs/chapter1/img/1.33.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

BIN
docs/chapter1/img/1.34.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 266 KiB

BIN
docs/chapter1/img/1.35.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

BIN
docs/chapter1/img/1.36.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

BIN
docs/chapter1/img/1.37.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

BIN
docs/chapter1/img/1.38.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

BIN
docs/chapter1/img/1.39.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 493 KiB

After

Width:  |  Height:  |  Size: 406 KiB

BIN
docs/chapter1/img/1.40.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

BIN
docs/chapter1/img/1.41.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

BIN
docs/chapter1/img/1.42.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/chapter1/img/1.43.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

BIN
docs/chapter1/img/1.44.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

BIN
docs/chapter1/img/1.45.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 425 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 346 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 775 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

After

Width:  |  Height:  |  Size: 442 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

After

Width:  |  Height:  |  Size: 252 KiB

100
docs/chapter10/chapter10.md Normal file
View File

@@ -0,0 +1,100 @@
# Imitation Learning
![](img/10.1.png)
`Imitation learning` 讨论的问题是,假设我们连 reward 都没有那要怎么办呢Imitation learning 又叫做 `learning from demonstration(示范学习)` `apprenticeship learning(学徒学习)``learning by watching(观察学习)`。在 Imitation learning 里面,你有一些 expert 的 demonstration那 machine 也可以跟环境互动,但它没有办法从环境里面得到任何的 reward它只能看着 expert 的 demonstration 来学习什么是好,什么是不好。其实,多数的情况,我们都没有办法真的从环境里面得到非常明确的 reward。举例来说如果是棋类游戏或者是电玩你有非常明确的 reward。但是其实多数的任务都是没有 reward 的。以 chat-bot 为例,机器跟人聊天,聊得怎么样算是好,聊得怎么样算是不好,你无法给出明确的 reward。所以很多 task 是根本就没有办法给出 reward 的。
虽然没有办法给出 reward但是收集 expert 的 demonstration 是可以做到的。举例来说,在自动驾驶汽车里面,虽然你没有办法给出自动驾驶汽车的 reward但你可以收集很多人类开车的纪录。在 chat-bot 里面,你可能没有办法定义什么叫做好的对话,什么叫做不好的对话。但是收集很多人的对话当作范例,这一件事情也是可行的。所以 imitation learning 的使用性非常高。假设你不知道该怎么定义 reward你就可以收集到 expert 的 demonstration你可以收集到一些范例的话你可以收集到一些很厉害的 agent比如说人跟环境实际上的互动的话那你就可以考虑 imitation learning 这个技术。在 imitation learning 里面,我们介绍两个方法。第一个叫做 `Behavior Cloning`,第二个叫做 `Inverse Reinforcement Learning` 或者又叫做 `Inverse Optimal Control`
## Behavior Cloning
![](img/10.2.png)
其实 `Behavior Cloning` 跟 supervised learning 是一模一样的。我们以自动驾驶汽车为例,你可以收集到人开自动驾驶汽车的所有资料,比如说可以通过行车记录器进行收集。看到这样子的 observation 的时候,人会决定向前。机器就采取跟人一样的行为,也向前,就结束了,这个就叫做 Behavior Cloning。Expert 做什么,机器就做一模一样的事,怎么让机器学会跟 expert 一模一样的行为呢?就把它当作一个 supervised learning 的问题,你去收集很多行车纪录器。然后再收集人在那个情境下会采取什么样的行为。你知道说人在 state $s_1$ 会采取action $a_1$人在state $s_2$ 会采取action $a_2$。人在state, $s_3$ 会采取action $a_3$。接下来你就learn 一个 network。这个 network 就是你的 actor他input $s_i$ 的时候你就希望他的output 是$a_i$,就这样结束了。它就是一个的 supervised learning 的problem。
![](img/10.3.png)
Behavior Cloning 虽然非常简单但它的问题是如果你只收集expert 的资料,你可能看过的 observation 会是非常 limited。举例来说假设你要 learn 一部自动驾驶汽车,自动驾驶汽车就是要过这个弯道。如果是 expert 的话,他就是把车顺着这个红线就开过去了。但假设你的 agent 很笨,他今天开着开着,就开到撞墙了,他永远不知道撞墙这种状况要怎么处理,为什么?因为 training data 里面从来没有撞过墙,所以他根本就不知道撞墙这一种 case 要怎么处理。或是打电玩,电玩也是一样,让人去玩 Mario那 expert 可能非常强他从来不会跳不上水管所以机器根本不知道跳不上水管时要怎么处理。人从来不会跳不上水管但是机器如果跳不上水管时就不知道要怎么处理。所以光是做Behavior Cloning 是不够的。只观察 expert 的行为是不够的,需要一个招数,这个招数叫作`Dataset Aggregation`
![](img/10.4.png)
我们会希望收集更多样性的 data而不是只收集 expert 所看到的 observation。我们会希望能够收集 expert 在各种极端的情况下他会采取什么样的行为。以自动驾驶汽车为例的话假设一开始你的actor 叫作 $\pi_1$,你让 $\pi_1$去开这个车。但车上坐了一个 expert。这个 expert 会不断地告诉machine 说,如果在这个情境里面,我会怎么样开。所以 $\pi_1$ 自己开自己的但是expert 会不断地表示他的想法。比如说在这个时候expert 可能说那就往前走。这个时候expert 可能就会说往右转。但 $\pi_1$ 是不管 expert 的指令的,所以他会继续去撞墙。虽然 expert 说往右转,但是不管他怎么下指令都是没有用的。$\pi_1$ 会自己做自己的事情因为我们要做的记录的是说今天expert 在 $\pi_1$ 看到这种observation 的情况下他会做什么样的反应。这个方法显然是有一些问题的因为每次你开一次自动驾驶汽车都会牺牲一个人。那你用这个方法你牺牲一个expert 以后,你就会得到说,人类在这样子的 state 下在快要撞墙的时候会采取什么样的反应。再把这个data 拿去train 新的 $\pi_2$。这个process 就反复继续下去,这个方法就叫做`Dataset Aggregation`
![](img/10.5.png)
Behavior Cloning 还有一个 issue 是说,机器会完全 copy expert 的行为,不管 expert 的行为是否有道理就算没有道理没有什么用的这是expert 本身的习惯,机器也会硬把它记下来。如果机器确实可以记住所有 expert 的行为,那也许还好,为什么呢?因为如果 expert 这么做,有些行为是多余的。但是没有问题,假设机器的行为可以完全仿造 expert 行为,那也就算了,那他是跟 expert 一样得好,只是做一些多余的事。但问题就是它是一个 machine它是一个 networknetwork 的capacity 是有限的。就算给 network training data它在training data 上得到的正确率往往也不是100%,他有些事情是学不起来的。这个时候,什么该学,什么不该学就变得很重要。
举例来说,在学习中文的时候,你的老师,他有语音,他也有行为,他也有知识,但其实只有语音部分是重要的,知识的部分是不重要的。也许 machine 只能够学一件事,也许他就只学到了语音,那没有问题。如果他只学到了手势,这样子就有问题了。所以让机器学习什么东西是需要 copy什么东西是不需要 copy这件事情是重要的。而单纯的 Behavior Cloning 就没有把这件事情学进来,因为机器只是复制 expert 所有的行为而已,它不知道哪些行为是重要,是对接下来有影响的,哪些行为是不重要的,是对接下来是没有影响的。
![](img/10.6.png)
Behavior Cloning 还有什么样的问题呢?在做 Behavior Cloning 的时候training data 跟 testing data 是 mismatch 的。我们可以用 Dataset Aggregation 的方法来缓解这个问题。这个问题是,在 training 跟 testing 的时候data distribution 其实是不一样的。因为在 reinforcement learning 里面action 会影响到接下来所看到的 state。我们是先有 state $s_1$,然后采取 action $a_1$action $a_1$ 其实会决定接下来你看到什么样的 state $s_2$。所以在 reinforcement learning 里面有一个很重要的特征,就是你采取了 action 会影响你接下来所看到的 state。如果做了Behavior Cloning 的话,我们只能观察到 expert 的一堆 state 跟 action 的pair。然后我们希望可以 learn 一个 $\pi^*$,我们希望 $\pi^*$ 跟 $\hat{\pi}$ 越接近越好。如果 $\pi^*$ 可以跟 $\hat{\pi}$ 一模一样的话,你 training 的时候看到的 state 跟 testing 的时候所看到的 state 会是一样的。因为虽然 action 会影响我们看到的 state但假设两个 policy 一模一样, 在同一个 state 都会采取同样的 action那你接下来所看到的 state 都会是一样的。但问题就是你很难让你的 learn 出来的 policy 跟expert 的 policy 一模一样。Expert 可是一个人network 要跟人一模一样,感觉很难吧。
如果你的 $\pi^*$ 跟 $\hat{\pi}$ 有一点误差。这个误差在一般 supervised learning problem 里面,每一个 example 都是 independent 的,也许还好。但对 reinforcement learning 的 problem 来说,你可能在某个地方就是失之毫厘,差之千里。可能在某个地方,也许 machine 没有办法完全复制 expert 的行为,它只复制了一点点,差了一点点,也许最后得到的结果就会差很多这样。所以 Behavior Cloning 并不能够完全解决 Imatation learning 这件事情。所以就有另外一个比较好的做法叫做 `Inverse Reinforcement Learning`
## Inverse RL
![](img/10.7.png)
为什么叫 Inverse Reinforcement Learning因为原来的 Reinforcement Learning 里面,有一个环境和一个 reward function。根据环境和 reward function通过 Reinforcement Learning 这个技术,你会找到一个 actor你会 learn 出一个optimal actor。但 Inverse Reinforcement Learning 刚好是相反的,你没有 reward function你只有一堆 expert 的 demonstration。但你还是有环境的。IRL 的做法是说假设我们现在有一堆 expert 的demonstration我们用 $\hat{\tau}$ 来代表expert 的demonstration。如果是在玩电玩的话每一个 $\tau$ 就是一个很会玩电玩的人玩一场游戏的纪录,如果是自动驾驶汽车的话,就是人开自动驾驶汽车的纪录。这一边就是 expert 的 demonstration每一个 $\tau$ 是一个 trajectory。
把所有 expert demonstration 收集起来然后使用Inverse Reinforcement Learning 这个技术。使用 Inverse Reinforcement Learning 技术的时候机器是可以跟环境互动的。但他得不到reward。他的 reward 必须要从 expert 那边推出来,有了环境和 expert demonstration 以后,去反推出 reward function 长什么样子。之前 reinforcement learning 是由 reward function 反推出什么样的 action、actor 是最好的。Inverse Reinforcement Learning 是反过来我们有expert 的demonstration我们相信他是不错的我就反推说expert 是因为什么样的 reward function 才会采取这些行为。你有了reward function 以后,接下来,你就可以套用一般的 reinforcement learning 的方法去找出 optimal actor。所以 Inverse Reinforcement Learning 是先找出 reward function找出 reward function 以后,再去用 Reinforcement Learning 找出 optimal actor。
把这个 reward function learn 出来,相较于原来的 Reinforcement Learning 有什么样好处。一个可能的好处是也许 reward function 是比较简单的。也许,虽然这个 expert 的行为非常复杂,但也许简单的 reward function 就可以导致非常复杂的行为。一个例子就是也许人类本身的 reward function 就只有活着这样,每多活一秒,你就加一分。但人类有非常复杂的行为,但是这些复杂的行为,都只是围绕着要从这个 reward function 里面得到分数而已。有时候很简单的 reward function 也许可以推导出非常复杂的行为。
![](img/10.8.png)
Inverse Reinforcement Learning 实际上是怎么做的呢?首先,我们有一个 expert $\hat{\pi}$,这个 expert 去跟环境互动,给我们很多 $\hat{\tau_1}$ 到 $\hat{\tau_n}$。如果是玩游戏的话,就让某一个电玩高手,去玩 n 场游戏。把 n 场游戏的 state 跟 action 的 sequence 都记录下来。接下来你有一个actor $\pi$一开始actor 很烂,这个 actor 也去跟环境互动。他也去玩了n 场游戏,他也有 n 场游戏的纪录。接下来,我们要反推出 reward function。怎么推出 reward function 呢?**原则就是 expert 永远是最棒的,是先射箭,再画靶的概念。**
Expert 去玩一玩游戏,得到这一些游戏的纪录,你的 actor 也去玩一玩游戏,得到这些游戏的纪录。接下来,你要定一个 reward function这个 reward function 的原则就是 expert 得到的分数要比 actor 得到的分数高,先射箭,再画靶。所以我们就 learn 出一个 reward function。你就找出一个 reward function。这个 reward function 会使 expert 所得到的 reward 大过于 actor 所得到的reward。你有了新的 reward function 以后,就可以套用一般 Reinforcement Learning 的方法去learn 一个actor这个actor 会针对 reward function 去 maximize 他的reward。他也会采取一大堆的action。但是今天这个 actor 虽然可以 maximize 这个 reward function采取一大堆的行为得到一大堆游戏的纪录。
但接下来,我们就改 reward function。这个 actor 就会很生气它已经可以在这个reward function 得到高分。但是他得到高分以后,我们就改 reward function仍然让 expert 可以得到比 actor 更高的分数。这个就是 `Inverse Reinforcement learning`。有了新的 reward function 以后,根据这个新的 reward function你就可以得到新的 actor新的 actor 再去跟环境做一下互动,他跟环境做互动以后, 你又会重新定义你的 reward function让 expert 得到的 reward 比 actor 大。
怎么让 expert 得到的 reward 大过 actor 呢?其实你在 learning 的时候你可以很简单地做一件事就是reward function 也许就是 neural network。这个 neural network 就是吃一个 $\tau$output 就是应该要给这个 $\tau$ 多少的分数。或者说,你假设觉得 input 整个$\tau$ 太难了。因为$\tau$ 是 s 和 a 的一个很强的sequence。也许他就是 input 一个 s 和 a 的 pair然后 output 一个real number。把整个 sequence整个$\tau$ 会得到的 real number 都加起来就得到 $R(\tau)$。在training 的时候,对于 $\left\{\hat{\tau}_{1}, \hat{\tau}_{2}, \cdots, \hat{\tau}_{N}\right\}$,我们希望它 output 的 R 越大越好。对于 $\left\{\tau_{1}, \tau_{2}, \cdots, \tau_{N}\right\}$,我们就希望它 R 的值越小越好。
什么叫做一个最好的 reward function。最后你 learn 出来的 reward function 应该就是 expert 和 actor 在这个 reward function 都会得到一样高的分数。最终你的 reward function 没有办法分辨出谁应该会得到比较高的分数。
通常在 train 的时候,你会 iterative 的去做。那今天的状况是这样,最早的 Inverse Reinforcement Learning 对 reward function 有些限制,他是假设 reward function 是 linear 的。如果reward function 是 linear 的话,你可以 prove 这个algorithm 会 converge。但是如果不是 linear 的,你就没有办法 prove 说它会 converge。你有没有觉得这个东西看起来还挺熟悉呢其实你只要把他换个名字说 actor 就是 generator然后说 reward function 就是discriminator它就是GAN。所以它会不会收敛这个问题就等于是问说 GAN 会不会收敛。如果你已经实现过,你会知道不一定会收敛。但除非你对 R 下一个非常严格的限制,如果你的 R 是一个 general 的network 的话,你就会有很大的麻烦。
![](img/10.9.png)
那怎么说它像是一个GAN我们来跟GAN 比较一下。GAN 里面你有一堆很好的图。然后你有一个generator一开始他根本不知道要产生什么样的图他就乱画。然后你有一个discriminatordiscriminator 的工作就是给画的图打分expert 画的图就是高分generator 画的图就是低分。你有discriminator 以后generator 会想办法去骗过 discriminator。Generator 会希望 discriminator 也会给它画的图高分。整个 process 跟 Inverse Reinforcement Learning 是一模一样的。
* 画的图就是 expert 的 demonstration。generator 就是actorgenerator 画很多图actor 会去跟环境互动,产生很多 trajectory。这些 trajectory 跟环境互动的记录,游戏的纪录其实就是等于 GAN 里面的这些图。
* 然后你 learn 一个reward function。Reward function 就是 discriminator。Rewards function 要给 expert 的 demonstration 高分,给 actor 互动的结果低分。
* 接下来actor 会想办法,从这个已经 learn 出来的 reward function 里面得到高分,然后 iterative 地去循环。跟GAN 其实是一模一样的,我们只是换个说法来而已。
![](img/10.10.png)
IRL 有很多的application举例来说可以用开来自动驾驶汽车。然后有人用这个技术来学开自动驾驶汽车的不同风格每个人在开车的时候其实你会有不同风格。举例来说能不能够压到线能不能够倒退要不要遵守交通规则等等。每个人的风格是不同的然后用 Inverse Reinforcement Learning 可以让自动驾驶汽车学会各种不同的开车风格。
![](img/10.11.png)
上图是文献上真实的例子,在这个例子里面, Inverse Reinforcement Learning 有一个有趣的地方,通常你不需要太多的 training data因为 training data 往往都是个位数。因为 Inverse Reinforcement Learning 只是一种 demonstration只是一种范例实际上机器可以去跟环境互动非常多次。所以在 Inverse Reinforcement Learning 的文献, 往往会看到说只用几笔 data 就训练出一些有趣的结果。
比如说在这个例子里面是要让自动驾驶汽车学会在停车场里面停。这边的demonstration 是这样,蓝色是终点,自动驾驶汽车要开到蓝色终点停车。给机器只看一行的四个 demonstration然后让他去学怎么样开车最后他就可以学出在红色的终点位置如果他要停车的话他会这样开。今天给机器看不同的demonstration最后他学出来开车的风格就会不太一样。举例来说上图第二行是不守规矩的开车方式因为他会开到道路之外这边他会穿过其他的车然后从这边开进去。所以机器就会学到说不一定要走在道路上他可以走非道路的地方。上图第三行是倒退来停车机器也会学会说他可以倒退
![](img/10.12.png)
这种技术也可以拿来训练机器人。你可以让机器人,做一些你想要他做的动作,过去如果你要训练机器人,做你想要他做的动作,其实是比较麻烦的。怎么麻烦呢?过去如果你要操控机器的手臂,你要花很多力气去写 program 才让机器做一件很简单的事看。假设你有 Imitation Learning 的技术你可以让人做一下示范然后机器就跟着人的示范来进行学习比如学会摆盘子拉着机器人的手去摆盘子机器自己动。让机器学会倒水人只教他20 次,杯子每次放的位置不太一样。用这种方法来教机械手臂。
## Third Person lmitation Learning
![](img/10.13.png)
其实还有很多相关的研究,举例来说,你在教机械手臂的时候,要注意就是也许机器看到的视野跟人看到的视野是不太一样的。在刚才那个例子里面,人跟机器的动作是一样的。但是在未来的世界里面,也许机器是看着人的行为学的。刚才是人拉着,假设你要让机器学会打高尔夫球,在刚才的例子里面就是人拉着机器人手臂去打高尔夫球,但是在未来有没有可能机器就是看着人打高尔夫球,他自己就学会打高尔夫球了呢?但这个时候,要注意的事情是机器的视野跟他真正去采取这个行为的时候的视野是不一样的。机器必须了解到当他是第三人的视角的时候,看到另外一个人在打高尔夫球,跟他实际上自己去打高尔夫球的时候,看到的视野显然是不一样的。但他怎么把他是第三人的时间所观察到的经验把它 generalize 到他是第一人称视角的时候所采取的行为,这就需要用到`Third Person Imitation Learning`的技术。
![](img/10.14.png)
这个怎么做呢?它的技术其实也是不只是用到 Imitation Learning他用到了 `Domain-Adversarial Training`。我们在讲 Domain-Adversarial Training 的时候我们有讲说这也是一个GAN 的技术。那我们希望今天有一个 extractor有两个不同 domain 的image通过 feature extractor 以后,没有办法分辨出他来自哪一个 domain。其实第一人称视角和第三人称视角Imitation Learning 用的技术其实也是一样的,希望 learn 一个 Feature Extractor机器在第三人称的时候跟他在第一人称的时候看到的视野其实是一样的就是把最重要的东西抽出来就好了。
## Recap: Sentence Generation & Chat-bot
![](img/10.15.png)
在讲 Sequence GAN 的时候,我们有讲过 Sentence Generation 跟 Chat-bot。那其实 Sentence Generation 或 Chat-bot 也可以想成是 Imitation Learning。机器在 imitate 人写的句子,你在写句子的时候,你写下去的每一个 word 都想成是一个 action所有的 word 合起来就是一个 episode。举例来说 sentence generation 里面,你会给机器看很多人类写的文字。你要让机器学会写诗,那你就要给他看唐诗三百首。人类写的文字其实就是 expert 的 demonstration。每一个词汇其实就是一个 action。今天你让机器做Sentence Generation 的时候其实就是在 imitate expert 的trajectory。Chat-bot 也是一样在Chat-bot 里面你会收集到很多人互动对话的纪录,那些就是 expert 的 demonstration。
如果我们今天单纯用 maximum likelihood 这个技术来 maximize 会得到 likelihood这个其实就是behavior cloning。我们今天做 behavior cloning 就是看到一个 state接下来预测我们会得到什么样的 action。看到一个state然后有一个 ground truth 告诉机器说什么样的 action 是最好的。在做 likelihood 的时候也是一样given sentence 已经产生的部分。接下来 machine 要 predict 说接下来要写哪一个word 才是最好的。所以,其实 maximum likelihood 在做Sequence generation 的时候,它对应到 Imitation Learning 里面就是 behavior cloning。只有 maximum likelihood 是不够的,我们想要用 Sequence GAN其实 Sequence GAN 就是对应到 Inverse Reinforcement LearningInverse Reinforcement Learning 就是一种 GAN 的技术。你把 Inverse Reinforcement Learning 的技术放在 Sentence generation放到 Chat-bot 里面,其实就是 Sequence GAN 跟它的种种的变形。

BIN
docs/chapter10/img/10.1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

BIN
docs/chapter10/img/10.2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 KiB

BIN
docs/chapter10/img/10.3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

BIN
docs/chapter10/img/10.4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

BIN
docs/chapter10/img/10.5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

BIN
docs/chapter10/img/10.6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

BIN
docs/chapter10/img/10.7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

BIN
docs/chapter10/img/10.8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

BIN
docs/chapter10/img/10.9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

View File

@@ -0,0 +1,81 @@
# DDPG
## 离散动作 vs. 连续动作
![](img/11.1.png)
离散动作与连续动作是相对的概念,一个是可数的,一个是不可数的。 在 CartPole 环境中,可以有向左推小车、向右推小车两个动作。在 Frozen Lake 环境中,小乌龟可以有上下左右四个动作。在 Atari 的 Pong 游戏中游戏有6个按键的动作可以输出。
但在实际情况中,经常会碰到连续动作空间的情况,也就是输出的动作是不可数的。比如说推小车力的大小, 选择下一时刻方向盘的转动角度或者四轴飞行器的四个螺旋桨给的电压的大小等等。
![](img/11.2.png)
对于这些连续的动作控制空间Q-learning、DQN 等算法是没有办法处理的。那我们怎么输出连续的动作呢,这个时候,万能的神经网络又出现了。在上面这个离散动作的场景下,比如说我输出上下或是停止这几个动作。有几个动作,神经网络就输出几个概率值。我们用 $\pi_\theta(a_t|s_t)$ 来表示这个随机性的策略。
然后在连续的动作场景下,比如说我要输出这个机器人手臂弯曲的角度,这样子的一个动作,我们就输出一个具体的浮点数。我们用 $\mu_{\theta}(s_t)$ 来代表这个确定性的策略。
我们再解释一下随机性策略跟确定性策略。
* 对随机性的策略来说,我们输入某一个状态 s采取某一个 action 的可能性并不是百分之百,而是有一个概率 P 的,就好像抽奖一样,根据概率随机抽取一个动作。
* 而对于确定性的策略来说它没有概率的影响。当神经网络的参数固定下来了之后输入同样的state必然输出同样的 action这就是确定性的策略。
![](img/11.3.png)
* 要输出离散动作的话,我们就是加一层 softmax 层来确保说所有的输出是动作概率,而且所有的动作概率加和为 1。
* 要输出连续的动作的话,一般我们可以在输出层这里加一层 tanh。tanh 的图像的像右边这样子,它的作用就是可以把输出限制到 [-1,1] 之间。我们拿到这个输出后,就可以根据实际动作的一个范围再做一下缩放,然后再输出给环境。比如神经网络输出一个浮点数是 2.8,然后经过 tanh 之后,它就可以被限制在 [-1,1] 之间,它输出 0.99。然后假设说小车的一个速度的那个动作范围是 [-2,2] 之间,那我们就按比例从 [-1,1] 扩放到 [-2,2]0.99 乘 2最终输出的就是1.98,作为小车的速度或者说推小车的力输出给环境。
## DDPG
![](img/11.4.png)
在连续控制领域,比较经典的强化学习算法就是 `DDPG(Deep Deterministic Policy Gradient)`。DDPG 的特点可以从它的名字当中拆解出来,拆解成 Deep、Deterministic 和 Policy Gradient。
* Deep 是因为用了神经网络。
* Deterministic 表示 DDPG 输出的是一个确定性的动作,可以用于连续动作的一个环境。
* Policy Gradient 代表的是它用到的是策略网络。REINFORCE 算法每隔一个 episode 就更新一次,但 DDPG 网络是每个 step 都会更新一次 policy 网络,也就是说它是一个单步更新的 policy 网络。
DDPG 是 DQN 的一个扩展的版本。在 DDPG 的训练中,它借鉴了 DQN 的技巧:目标网络和经验回放。经验回放这一块跟 DQN 是一样的。但是 target network 这一块的更新跟 DQN 有点不一样。
![](img/11.5.png)
提出 DDPG 是为了让 DQN 可以扩展到连续的动作空间,就是我们刚才提到的小车速度、角度和电压的电流量这样的连续值。所以 DDPG 直接在 DQN 基础上加了一个策略网络,就是蓝色的这个,用来直接输出动作值。所以 DDPG 需要一边学习 Q网络一边学习策略网络。Q网络的参数用 $w$ 来表示。策略网络的参数用 $\theta$ 来表示。我们称这样的结构为 `Actor-Critic` 的结构。
![](img/11.6.png)
通俗的去解释一下这个 Actor-Critic 的结构,策略网络扮演的就是 actor 的角色它负责对外展示输出输出舞蹈动作。Q网络就是评论家(critic),它会在每一个 step 都对 actor 输出的动作做一个评估,打一个分,估计一下它做一次的 action 未来能有多少收益,也就是去估计这个 actor 输出的这个 action 的 Q值大概是多少即 $Q_w(s,a)$。 Actor 就需要根据舞台目前的状态来做出一个 action。
评论家就是评委,它需要根据舞台现在的状态和演员输出的 action 这两个值对 actor 刚刚的表现去打一个分数 $Q_w(s,a)$。所以 actor 就是要根据评委的打分来调整自己的策略。也就是更新 actor 的神经网络参数 $\theta$ 争取下次可以做得更好。而 critic 就是要根据观众的反馈,也就是环境的反馈 reward 来调整自己的打分策略,也就是要更新 critic 的神经网络的参数 $w$ ,它的目标是要让每一场表演都获得观众尽可能多的欢呼声跟掌声,也就是要最大化未来的总收益。其实最开始训练的时候,这两个神经网络参数是随机的。所以 critic 最开始是随机打分的,然后 actor 也跟着乱来,就随机表演,随机输出动作。但是由于我们有环境反馈的 reward 存在,所以 critic 的评分会越来越准确,也会评判的那个 actor 的表现会越来越好。既然 actor 是一个神经网络,是我们希望训练好的这个策略网络,那我们就需要计算梯度来去更新优化它里面的参数 $\theta$ 。简单的说,我们希望调整 actor 的网络参数,使得评委打分尽可能得高。注意,这里的 actor 是不管观众的,它只关注评委,它就是迎合评委的打分,打的这个 $Q_w(s,a)$ 而已。
![](img/11.7.png)
接下来就是类似 DQN。DQN 的最佳策略是想要学出一个很好的 Q网络。 学好这个网络之后,我们希望选取的那个动作使你的 Q值最大。DDPG 的目的也是为了求解让 Q值最大的那个 action。Actor 只是为了迎合评委的打分而已,所以用来优化策略网络的梯度就是要最大化这个 Q 值,所以构造的 loss 函数就是让 Q 取一个负号。我们写代码的时候要做的就是把这个 loss 函数扔到优化器里面,它就会自动最小化 loss也就是最大化这个 Q。然后这里注意除了策略网络要做优化DDPG 还有一个 Q网络也要优化。评委一开始其实也不知道怎么评分它也是在一步一步的学习当中慢慢地去给出准确的打分。那我们优化 Q网络的方法其实跟 DQN 优化 Q网络的方法是一模一样的。我们用真实的 reward $r$ 和下一步的 Q 即 Q' 来去拟合未来的收益也就是 Q_target。
然后让 Q网络的输出去逼近这个 Q_target。所以构造的 loss function 就是直接求这两个值的均方差。构造好loss 后,之后我们就扔进去那个优化器,让它自动去最小化 loss 就好了。
![](img/11.8.png)
那我们把两个网络的 loss function 就可以构造出来。我们可以看到策略网络的 loss function 是一个复合函数。我们把那个 $a = \mu_\theta(s)$ 代进去,最终策略网络要优化的是策略网络的参数 $\theta$ 。
Q 网络要优化的是那个 Q 的输出 $Q_w(s,a)$ 和那个 Q_target 之间的一个均方差。但是 Q网络的优化存在一个和 DQN 一模一样的问题就是它后面的这个 Q_target 是不稳定的。这个在之前的 DQN 有讲过。后面的 $Q_{\bar{w}}\left(s^{\prime}, a^{\prime}\right)$ 也是不稳定的。因为 $Q_{\bar{w}}\left(s^{\prime}, a^{\prime}\right)$ 也是一个预估的值。为了稳定这个 Q_target。DDPG 分别给 Q网络和策略网络都搭建了 target network专门就是为了用来稳定这个 Q_target。
target Q 网络就为了来计算 Q_target 里面的 $Q_{\bar{w}}\left(s^{\prime}, a^{\prime}\right)$。然后 $Q_{\bar{w}}\left(s^{\prime}, a^{\prime}\right)$ 里面的需要的 next action $a'$ 就是通过 target_P 网络来去输出,即 $a^{\prime}=\mu_{\bar{\theta}}\left(s^{\prime}\right)$。
为了区分前面的 Q网络和策略网络以及后面的 target_Q 网络和 target_p 策略网络。前面的网络的参数是 $w$,后面的网络的参数是 $\bar{w}$。这就是为什么我们去看一些 DDPG 的文章,会发现 DDPG 会有四个网络。策略网络的 target 网络 和 Q网络的 target 网络就是颜色比较深的这两个。它只是为了让计算 Q_target 的时候能够更稳定一点而已。因为这两个网络也是固定一段时间的参数之后再跟评估网络同步一下最新的参数。
这里面训练需要用到的数据就是 $s,a,r,s'$。我们只需要用到这四个数据,我们就用 Replay Memory 把这些数据存起来,然后再 sample 进来训练就好了。这个经验回放的技巧跟 DQN 是一模一样的。注意,因为 DDPG 使用了经验回放这个技巧,所以 DDPG 是一个 `off-policy` 的算法。
## Exploration vs. Exploitation
DDPG 通过 off-policy 的方式来训练一个确定性策略。因为策略是确定的,如果 agent 使用同策略来探索,在一开始的时候,它会很可能不会尝试足够多的 action 来找到有用的学习信号。为了让 DDPG 的策略更好地探索,我们在训练的时候给它们的 action 加了噪音。DDPG 的原作者推荐使用时间相关的 [OU noise](https://en.wikipedia.org/wiki/OrnsteinUhlenbeck_process),但最近的结果表明不相关的、均值为 0 的 Gaussian noise 的效果非常好。由于后者更简单,因此我们更喜欢使用它。为了便于获得更高质量的训练数据,你可以在训练过程中把噪声变小。
在测试的时候,为了查看策略利用它学到的东西的表现,我们不会在 action 中加噪音。
## References
* [百度强化学习课](https://aistudio.baidu.com/aistudio/education/lessonvideo/460292)
* [OpenAI Spinning Up ](https://spinningup.openai.com/en/latest/algorithms/ddpg.html#)

BIN
docs/chapter11/img/11.1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

BIN
docs/chapter11/img/11.2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

BIN
docs/chapter11/img/11.3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 642 KiB

BIN
docs/chapter11/img/11.4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

BIN
docs/chapter11/img/11.5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

BIN
docs/chapter11/img/11.6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

BIN
docs/chapter11/img/11.7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

BIN
docs/chapter11/img/11.8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 633 KiB

View File

@@ -1,227 +1,181 @@
# PPO
## From On-policy to Off-policy
在讲 PPO 之前,我们先讲一下 on-policy 和 off-policy 这两种 training 方法的区别。
在 reinforcement learning 里面,我们要 learn 的就是一个agent。
# 表格型方法
* 如果要 learn 的 agent 跟和环境互动的 agent 是同一个的话, 这个叫做`on-policy(同策略)`
* 如果要 learn 的 agent 跟和环境互动的 agent 不是同一个的话, 那这个叫做`off-policy(异策略)`
比较拟人化的讲法是如果要学习的那个 agent一边跟环境互动一边做学习这个叫 on-policy。 如果它在旁边看别人玩,通过看别人玩来学习的话,这个叫做 off-policy。
为什么我们会想要考虑 off-policy ?让我们来想想 policy gradient。Policy gradient 是 on-policy 的做法,因为在做 policy gradient 时,我们需要有一个 agent、一个 policy 和一个 actor。这个 actor 先去跟环境互动去搜集资料,搜集很多的 $\tau$,根据它搜集到的资料,会按照 policy gradient 的式子去 update policy 的参数。所以 policy gradient 是一个 on-policy 的 algorithm。
这节课我们通过最简单的`表格型的方法`来讲解如何使用 value-based 方法去求解强化学习。
![](img/2.1.png)
PPO 是 policy gradient 的一个变形,它是现在 OpenAI default reinforcement learning 的 algorithm
强化学习的三个重要的要素状态动作和奖励。强化学习智能体跟环境是一步一步交互的就是我先观察一下状态然后再输入动作。再观察一下状态再输出动作拿到这些reward 。它是一个跟时间相关的一个序列决策的问题
举个例子,在 $t-1$ 时刻,我看到了熊对我招手,那我下意识的可能输出的动作就是我赶紧跑路。熊看到了有人跑了,可能就觉得发现猎物,开始发动攻击。而在 $t$ 时刻的话,我如果选择装死的动作,可能熊咬了咬我那个摔了几下就发现就觉得挺无趣的,可能会走开。那这个时候,我再跑路的话可能就跑路成功了,就是大概是这样子的一个序列决策的过程。
当然在输出每一个动作之前,其实你都是可以选择不同的动作。比如说在 $t$ 时刻,我选择跑路的时候,熊已经追上来了,如果说 $t$ 时刻,我没有选择装死,而我是选择跑路的话,这个时候熊已经追上了,那这个时候,其实我有两种情况转移到不同的状态去,就我有一定的概率可以逃跑成功,也有很大的概率我会逃跑失败。那我们就用状态转移概率 $p\left[s_{t+1}, r_{t} \mid s_{t}, a_{t}\right]$ 来表述说在 $s_t$ 的状态选择了 $a_t$ 的动作的时候,转移到 $s_{t+1}$ ,而且拿到 $r_t$ 的概率是多少。
我们就说这样子的一个状态转移概率是符合马尔科夫的,因为这个状态转移概率,它是下一时刻的状态是取决于当前的状态,它和之前的 $s_{t-1}$ 和 $s_{t-2}$ 都没有什么关系。然后再加上说这个过程也取决于智能体跟环境交互的这个$a_t$ ,所以有一个决策的一个过程在里面。我们就称这样的一个过程为马尔可夫决策过程(MDP)。
MDP 就是序列决策这样一个经典的表达方式。MDP 也是强化学习里面一个非常基本的学习框架。像之前的这四个状态、动作、奖励和状态转移概率SAPR这四个合集就构成了强化学习 MDP 的四元组,那后面其实也可能会再加个衰减因子构成五元组。
$$
\nabla \bar{R}_{\theta}=E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right]
$$
问题是上面这个 update 的式子中的 $E_{\tau \sim p_{\theta}(\tau)}$ 应该是你现在的 policy $\theta$ 所 sample 出来的 trajectory $\tau$ 做 expectation。一旦 update 了参数,从 $\theta$ 变成 $\theta'$ $p_\theta(\tau)$这个概率就不对了之前sample 出来的 data 就变的不能用了。所以 policy gradient 是一个会花很多时间来 sample data 的 algorithm你会发现大多数时间都在 sample dataagent 去跟环境做互动以后,接下来就要 update 参数。你只能 update 参数一次。接下来你就要重新再去 collect data 然后才能再次update 参数,这显然是非常花时间的。所以我们想要从 on-policy 变成 off-policy。 这样做就可以用另外一个policy 另外一个actor $\theta'$ 去跟环境做互动。用 $\theta'$ collect 到的data 去训练 $\theta$。假设我们可以用 $\theta'$ collect 到的data 去训练 $\theta$,意味着说我们可以把$\theta'$ collect 到的data 用非常多次。我们可以执行 gradient ascent 好几次,我们可以 update 参数好几次, 都只要用同一笔data 就好了。因为假设 $\theta$ 有能力学习另外一个actor $\theta'$ 所 sample 出来的 data 的话, 那$\theta'$ 就只要sample 一次也许sample 多一点的data 让$\theta$ 去update 很多次,这样就会比较有效率。
![](img/2.2.png)
具体怎么做呢?这边就需要介绍 `important sampling` 的概念。假设你有一个function $f(x)$,你要计算从 p 这个 distribution sample x再把 x 带到 f 里面,得到$f(x)$。你要该怎么计算这个 $f(x)$ 的期望值?假设你不能对 p 这个distribution 做积分的话,那你可以从 p 这个 distribution 去 sample 一些data $x^i$。把 $x^i$ 代到 $f(x)$ 里面,然后取它的平均值,就可以近似 $f(x)$ 的期望值。
现在有另外一个问题,我们没有办法从 p 这个 distribution 里面 sample data。假设我们不能从 p sample data只能从另外一个 distribution q 去 sample dataq 可以是任何 distribution。我们不能够从 p 去sample data但可以从 q 去 sample $x$。我们从 q 去 sample $x^i$ 的话就不能直接套下面的式子。
$$
E_{x \sim p}[f(x)] \approx \frac{1}{N} \sum_{i=1}^N f(x^i)
$$
因为上式是假设你的 $x$ 都是从 p sample 出来的。所以做一个修正,修正是这样子的。期望值$E_{x \sim p}[f(x)]$其实就是$\int f(x) p(x) dx$,我们对其做如下的变换:
$$
\int f(x) p(x) d x=\int f(x) \frac{p(x)}{q(x)} q(x) d x=E_{x \sim q}[f(x){\frac{p(x)}{q(x)}}]
$$
我们就可以写成对 q 里面所 sample 出来的 x 取期望值。我们从q 里面 sample x然后再去计算$f(x) \frac{p(x)}{q(x)}$,再去取期望值。所以就算我们不能从 p 里面去 sample data只要能够从 q 里面去sample data然后代入上式你就可以计算从 p 这个distribution sample x 代入 f 以后所算出来的期望值。
这边是从 q 做 sample所以从 q 里 sample 出来的每一笔data你需要乘上一个 weight 来修正这两个 distribution 的差异weight 就是$\frac{p(x)}{q(x)}$。$q(x)$ 可以是任何 distribution唯一的限制就是 $q(x)$ 的概率是 0 的时候,$p(x)$ 的概率不为 0不然这样会没有定义。假设 $q(x)$ 的概率是 0 的时候,$p(x)$ 的概率也都是 0 的话,那这样 $p(x)$ 除以 $q(x)$是有定义的。所以这个时候你就可以 apply important sampling 这个技巧。你就可以从 p 做 sample 换成从 q 做 sample。
我们把这些可能的动作和可能的状态转移的关系画成这样子的一个树状图。它们之间的关系就是一个从 $s_t$ 到 $a_t$ ,再到 $s_{t+1}$ ,再到 $a_{t+1}$,再到 $s_{t+2}$ 这样子的一个过程。
我们去跟环境交互,我们只能走完整的一条通路。这里面产生了一系列的一个决策的过程,就是我们跟环境交互产生了一个经验。然后我们会使用 P 函数和 R 函数来去描述环境。P 函数就是状态转移的概率R 函数就是Reward function。P函数实际上反映的是环境的一个随机性。比方说在熊发怒的情况下我如果选择装死假设熊看到人装死就一定会走的话我们就称在这里面的这个状态转移概率就是百分之百。但如果说在熊发怒的情况下我选择跑路而导致说我有可能跑成功以及跑失败出现这两种情况。那我们就可以用概率去表达一下说转移到其中一种情况的概率大概 10%另外一种情况的概率大概是90%会跑失败。**如果我们知道这些状态转移概率和奖励函数的话,我们就说这个环境是已知的,因为我们是用这两个函数去描述环境的。**如果是已知的话,我们其实可以用动态规划去计算说,我如果要逃脱熊,那么能够逃脱熊概率最大的最优策略是什么。很多强化学习的经典的算法都是 model-free 的,就是环境是未知的这样子的一个情况下,我们强化学习怎么去解决。
![](img/2.3.png)
因为现实世界中人类第一次遇到熊之前我们根本不知道我们能不能跑得过熊。所以刚刚那个10%、90%的概率也就是虚构出来的概率,熊到底在什么时候会往什么方向去转变的话,我们经常是不知道的。我们是处在一个未知的环境里的,也就是这一系列的决策的 P 函数和 R 函数是未知的。这就是 model-based 跟 model-free 的一个最大的区别。强化学习就是可以用来解决用完全未知的和随机的环境。
Important sampling 有一些 issue。虽然理论上你可以把 p 换成任何的 q。但是在实现上 p 和 q 不能够差太多。差太多的话,会有一些问题。什么样的问题呢?
强化学习要像人类一样去学习了,人类学习的话就是一条路一条路的去尝试一下,先走一条路,我看看结果到底是什么。多试几次,只要能活命的,我们其实可以慢慢的了解哪个状态会更好。我们用价值函数 $V(s)$ 来代表这个状态是好的还是坏的。然后用这个 Q 函数来判断说在什么状态下做什么动作能够拿到最大奖励我们用Q函数来表示这个状态动作值。
$$
E_{x \sim p}[f(x)]=E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]
$$
虽然上式成立。但上式左边是$f(x)$ 的期望值它的distribution 是 p上式右边是$f(x) \frac{p(x)}{q(x)}$ 的期望值它的distribution 是 q。如果不是算期望值而是算 variance 的话。这两个variance 是不一样的。两个 random variable 的 mean 一样,并不代表它的 variance 一样。
我们可以代一下方差的公式
$$
\operatorname{Var}_{x \sim p}[f(x)]=E_{x \sim p}\left[f(x)^{2}\right]-\left(E_{x \sim p}[f(x)]\right)^{2}
$$
$$
\begin{aligned}
\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right] &=E_{x \sim q}\left[\left(f(x) \frac{p(x)}{q(x)}\right)^{2}\right]-\left(E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]\right)^{2} \\
&=E_{x \sim p}\left[f(x)^{2} \frac{p(x)}{q(x)}\right]-\left(E_{x \sim p}[f(x)]\right)^{2}
\end{aligned}
$$
$\operatorname{Var}_{x \sim p}[f(x)]$ 和 $\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$ 的差别在第一项是不同的, $\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$ 的第一项多乘了$\frac{p(x)}{q(x)}$,如果$\frac{p(x)}{q(x)}$ 差距很大的话, $\operatorname{Var}_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$的 variance 就会很大。所以虽然理论上它们的expectation 一样,也就是说,你只要对 p 这个distribution sample 够多次q 这个distribution sample 够多你得到的结果会是一样的。但是假设你sample 的次数不够多因为它们的variance 差距是很大的,所以你就有可能得到非常大的差别。
![](img/2.4.png)
举个例子,当 $p(x)$ 和 $q(x)$ 差距很大的时候,会发生什么样的问题。假设蓝线是 $p(x)$ 的distribution绿线是 $q(x)$ 的 distribution红线是 $f(x)$。如果我们要计算$f(x)$的期望值,从 $p(x)$ 这个distribution 做 sample 的话,那显然 $E_{x \sim p}[f(x)]$ 是负的,因为左边那块区域 $p(x)$ 的概率很高,所以要 sample 的话,都会 sample 到这个地方,而 $f(x)$ 在这个区域是负的, 所以理论上这一项算出来会是负
接下来就会介绍 Q函数。在经过多次尝试和那个熊打交道之后人类就可以对熊的不同的状态去做出判断我们可以用状态动作价值的来表达说在某个状态下为什么动作 1 会比动作 2 好。因为动作1的价值比动作2要高。这个价值就叫 Q 函数。如果说这个 Q 表格是一张已经训练好的表格的话,那这一张表格就像是我们的一本生活手册。我们就知道在熊发怒的时候,装死的价值会高一点。在熊离开的时候,我们可能偷偷逃跑的会比较容易获救。这张表格里面 Q 函数的物理意义就是我选择了这个动作之后我最后面能不能成功,就是我需要去计算我在这个状态下,我选择了这个动作,后续能够一共拿到多少总收益。如果我可以预估未来的总收益的大小,我们当然知道在当前的这个状态下选择哪个动作,价值更高。我选择某个动作是因为我未来一共可以拿到的那个价值会更高一点。所以强化学习它的目标导向性很强,环境给了这个 reward 是一个非常重要的反馈,它就是根据环境的 reward 的反馈来去做选择
接下来我们改成从 $q(x)$ 这边做 sample因为 $q(x)$ 在右边这边的概率比较高所以如果你sample 的点不够的话那你可能都只sample 到右侧。如果你都只 sample 到右侧的话,你会发现说,算 $E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$这一项搞不好还应该是正的。你这边sample 到这些点,然后你去计算它们的$f(x) \frac{p(x)}{q(x)}$都是正的所以你sample 到这些点都是正的。 你取期望值以后,也都是正的。为什么会这样,因为你 sample 的次数不够多因为假设你sample 次数很少你只能sample 到右边这边。左边这边虽然概率很低,但也不是没有可能被 sample 到。假设你今天好不容易 sample 到左边的点,因为左边的点,$p(x)$ 和 $q(x)$ 是差很多的, 这边 $p(x)$ 很小,$q(x)$ 很大。今天 $f(x)$ 好不容易终于 sample 到一个负的,这个负的就会被乘上一个非常大的 weight ,这样就可以平衡掉刚才那边一直 sample 到 positive 的 value 的情况。最终你算出这一项的期望值终究还是负的。但前提是你要sample 够多次这件事情才会发生。但有可能sample 不够,$E_{x \sim p}[f(x)]$跟$E_{x \sim q}\left[f(x) \frac{p(x)}{q(x)}\right]$就有可能有很大的差距。这就是 importance sampling 的问题
![](img/2.5.png)未来的总收益是一个什么样的概念为什么可以用这个来评价当前这个动作是好是坏。举个例子假设说一辆车在路上当前是红灯我们直接走的那个收益就很低因为违反交通规则这是就是当前的单步收益。可是如果我们这是一辆救护车我们正在运送病人把病人快速送达医院的收益非常的高而且越快你的收益越大。很可能是我们这个时候应该要闯红灯因为未来的远期收益太高了。这也是为什么说强化学习需要去学习远期的收益因为现实世界当中这个奖励往往是延迟的是有delay 的
![](img/2.5.png)
现在要做的事情就是把 importance sampling 用在 off-policy 的 case。把 on-policy training 的algorithm 改成 off-policy training 的 algorithm。怎么改呢之前我们是拿 $\theta$ 这个policy 去跟环境做互动sample 出trajectory $\tau$,然后计算$R(\tau) \nabla \log p_{\theta}(\tau)$。
现在我们不用$\theta$ 去跟环境做互动,假设有另外一个 policy $\theta'$它就是另外一个actor。它的工作是他要去做demonstration$\theta'$ 的工作是要去示范给$\theta$ 看。它去跟环境做互动,告诉 $\theta$ 说,它跟环境做互动会发生什么事。然后,借此来训练$\theta$。我们要训练的是$\theta$ $\theta'$ 只是负责做 demo负责跟环境做互动。
我们现在的$\tau$ 是从 $\theta'$ sample 出来的,是拿 $\theta'$ 去跟环境做互动。所以sample 出来的 $\tau$ 是从 $\theta'$ sample 出来的这两个distribution 不一样。但没有关系,假设你本来是从 p 做sample但你发现你不能够从 p 做sample所以我们不拿$\theta$ 去跟环境做互动。你可以把 p 换 q然后在后面这边补上一个 importance weight。现在的状况就是一样把 $\theta$ 换成 $\theta'$ 后要补上一个importance weight $\frac{p_{\theta}(\tau)}{p_{\theta^{\prime}}(\tau)}$。这个 importance weight 就是某一个 trajectory $\tau$ 用 $\theta$ 算出来的概率除以这个 trajectory $\tau$,用$\theta'$ 算出来的概率。这一项是很重要的因为今天你要learn 的是actor $\theta$ 和 $\theta'$ 是不太一样的。$\theta'$ 会见到的情形跟 $\theta$ 见到的情形不见得是一样的,所以中间要做一个修正的项。
现在的data 不是从$\theta$ sample 出来,是从 $\theta'$ sample 出来的。从$\theta$ 换成$\theta'$ 有什么好处呢?因为现在跟环境做互动是$\theta'$ 而不是$\theta$。所以 sample 出来的东西跟 $\theta$ 本身是没有关系的。所以你就可以让 $\theta'$ 做互动 sample 一大堆的data$\theta$ 可以update 参数很多次。然后一直到 $\theta$ train 到一定的程度update 很多次以后,$\theta'$ 再重新去做sample这就是on-policy 换成off-policy 的妙用。
所以我们一般会从当前状态开始,后续有可能会收到所有收益加起来计算。当前动作的 Q 的价值,让 Q 的价值可以真正的代表当前这个状态动作的真正的价值。
![](img/2.6.png)
实际在做 policy gradient 的时候,我们并不是给整个 trajectory $\tau$ 都一样的分数而是每一个state-action 的pair 会分开来计算。实际上 update gradient 的时候,我们的式子是长这样子的。
$$
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta}}\left[A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]
$$
我们用 $\theta$ 这个actor 去sample 出$s_t$ 跟$a_t$sample 出state 跟action 的pair我们会计算这个state 跟action pair 它的advantage 就是它有多好。$A^{\theta}\left(s_{t}, a_{t}\right)$就是 accumulated 的 reward 减掉 bias这一项就是估测出来的。它要估测的是在state $s_t$ 采取action $a_t$ 是好的,还是不好的。那接下来后面会乘上$\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$,也就是说如果$A^{\theta}\left(s_{t}, a_{t}\right)$是正的,就要增加概率, 如果是负的,就要减少概率。
那现在用了 importance sampling 的技术把 on-policy 变成 off-policy就从 $\theta$ 变成 $\theta'$。所以现在$s_t$、$a_t$ 是$\theta'$ 另外一个actor 跟环境互动以后所 sample 到的data。 但是拿来训练要调整参数是 model $\theta$。因为 $\theta'$ 跟 $\theta$ 是不同的model所以你要做一个修正的项。这项修正的项就是用 importance sampling 的技术,把$s_t$、$a_t$ 用 $\theta$ sample 出来的概率除掉$s_t$、$a_t$ 用 $\theta'$ sample 出来的概率。
$$
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{P_{\theta}\left(s_{t}, a_{t}\right)}{P_{\theta^{\prime}}\left(s_{t}, a_{t}\right)} A^{\theta}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]
$$
这边 $A^{\theta}(s_t,a_t)$ 有一个上标 $\theta$$\theta$ 代表说这个是 actor $\theta$ 跟环境互动的时候所计算出来的 A。但是实际上从 $\theta$ 换到 $\theta'$ 的时候,$A^{\theta}(s_t,a_t)$ 应该改成 $A^{\theta'}(s_t,a_t)$为什么A 这一项是想要估测说现在在某一个 state 采取某一个 action接下来会得到 accumulated reward 的值减掉base line 。你怎么估 A 这一项,你就会看在 state $s_t$,采取 action $a_t$接下来会得到的reward 的总和再减掉baseline。之前是 $\theta$ 在跟环境做互动,所以你观察到的是 $\theta$ 可以得到的reward。但现在是 $\theta'$ 在跟环境做互动所以你得到的这个advantage 其实是根据 $\theta'$ 所estimate 出来的advantage。但我们现在先不要管那么多 我们就假设这两项可能是差不多的。
那接下来,我们可以拆解 $p_{\theta}\left(s_{t}, a_{t}\right)$ 和 $p_{\theta'}\left(s_{t}, a_{t}\right)$,即
$$
\begin{aligned}
p_{\theta}\left(s_{t}, a_{t}\right)&=p_{\theta}\left(a_{t}|s_{t}\right) p_{\theta}(s_t) \\
p_{\theta'}\left(s_{t}, a_{t}\right)&=p_{\theta'}\left(a_{t}|s_{t}\right) p_{\theta'}(s_t)
\end{aligned}
$$
于是我们得到下式:
$$
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} \frac{p_{\theta}\left(s_{t}\right)}{p_{\theta^{\prime}}\left(s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right]
$$
然后这边需要做一件事情是,假设 model 是 $\theta$ 的时候,你看到$s_t$ 的概率,跟 model 是$\theta'$ 的时候,你看到$s_t$ 的概率是差不多的,即$p_{\theta}(s_t)=p_{\theta'}(s_t)$。因为它们是一样的,所以你可以把它删掉,即
$$
=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)\right] \quad(1)
$$
为什么可以假设它是差不多的。举例来说会看到什么state 往往跟你会采取什么样的action 是没有太大的关系的。比如说你玩不同的 Atari 的游戏,其实你看到的游戏画面都是差不多的,所以也许不同的 $\theta$ 对 $s_t$ 是没有影响的。但是有一个更直觉的理由就是这一项到时候真的要你算,你会算吗?因为想想看这项要怎么算,这一项你还要说我有一个参数$\theta$,然后拿$\theta$ 去跟环境做互动,算$s_t$ 出现的概率,这个你根本很难算。尤其是你如果 input 是image 的话, 同样的 $s_t$ 根本就不会出现第二次。你根本没有办法估这一项, 所以干脆就无视这个问题。
但是 $p_{\theta}(a_t|s_t)$很好算。你手上有$\theta$ 这个参数它就是个network。你就把$s_t$ 带进去,$s_t$ 就是游戏画面你把游戏画面带进去它就会告诉你某一个state 的 $a_t$ 概率是多少。我们其实有个 policy 的network把 $s_t$ 带进去,它会告诉我们每一个 $a_t$ 的概率是多少。所以
$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}$ 这一项,你只要知道$\theta$ 和 $\theta'$ 的参数就可以算。
现在我们得到一个新的objective function。
$$
J^{\theta^{\prime}}(\theta)=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right]
$$
式(1)是 gradient其实我们可以从 gradient 去反推原来的 objective function。这边有一个公式
$$
\nabla f(x)=f(x) \nabla \log f(x)
$$
我们可以用这个公式来反推objective function要注意一点对 $\theta$ 求梯度时,$p_{\theta^{\prime}}(a_{t} | s_{t})$ 和 $A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)$ 都是常数。
所以实际上当我们apply importance sampling 的时候要去optimize 的那一个objective function 就长这样子,我们把它写作$J^{\theta^{\prime}}(\theta)$。为什么写成$J^{\theta^{\prime}}(\theta)$ 呢,这个括号里面那个$\theta$ 代表我们要去optimize 的那个参数。$\theta'$ 是说我们拿 $\theta'$ 去做demonstration就是现在真正在跟环境互动的是$\theta'$。因为 $\theta$ 不跟环境做互动,是 $\theta'$ 在跟环境互动。
然后你用$\theta'$ 去跟环境做互动sample 出$s_t$、$a_t$ 以后,你要去计算$s_t$ 跟$a_t$ 的advantage然后你再去把它乘上$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}$。$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)}$是好算的,$A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)$ 可以从这个 sample 的结果里面去估测出来的,所以 $J^{\theta^{\prime}}(\theta)$ 是可以算的。实际上在 update 参数的时候,就是按照式(1) 来 update 参数。
## PPO
但是有的时候你目光放的太长远不好,因为如果说事情很快就结束的话,你考虑到最后一步的收益无可厚非,可是如果说是一个持续的没有尽头的任务,你单纯的把所有未来的收益全部相加,作为当前的状态价值就很不合理。股票的例子就很典型了,我们要关注的是累积的收益。可是如果说十年之后才有一次大涨大跌,你要把十年后的收益也作为当前动作的考虑因素,显然我们不会这么做。那我们会怎么办呢,就有句俗话说得好,就对远一点的东西呢,我们就当做近视就不需要看得太清楚,我们就可以适当引入这个衰减因子 $\gamma$ 来去计算这个未来总收益。$\gamma \in [0,1]$ 。越往后 $\gamma^n$ 就会越小,也就是说越后面的收益对当前价值的影响就会越小。
![](img/2.7.png)
我们可以把 on-policy 换成 off-policy但 importance sampling 有一个 issue如果 $p_{\theta}\left(a_{t} | s_{t}\right)$ 跟 $p_{\theta'}\left(a_{t} | s_{t}\right)$ 差太多的话,这两个 distribution 差太多的话importance sampling 的结果就会不好。怎么避免它差太多呢?这个就是 `Proximal Policy Optimization (PPO) ` 在做的事情。它实际上做的事情就是这样,在 off-policy 的方法里要optimize 的是 $J^{\theta^{\prime}}(\theta)$。但是这个 objective function 又牵涉到 importance sampling。在做 importance sampling 的时候,$p_{\theta}\left(a_{t} | s_{t}\right)$ 不能跟 $p_{\theta'}\left(a_{t} | s_{t}\right)$差太多。你做 demonstration 的 model 不能够跟真正的 model 差太多,差太多的话 importance sampling 的结果就会不好。我们在 training 的时候,多加一个 constrain。这个constrain 是 $\theta$ 跟 $\theta'$ output 的 action 的 KL divergence简单来说这一项的意思就是要衡量说 $\theta$ 跟 $\theta'$ 有多像。
然后我们希望在 training 的过程中learn 出来的 $\theta$ 跟 $\theta'$ 越像越好。因为如果 $\theta$ 跟 $\theta'$ 不像的话,最后的结果就会不好。所以在 PPO 里面有两个式子,一方面是 optimize 本来要 optimize 的东西,但再加一个 constrain。这个 constrain 就好像那个 regularization 的 term 一样,在做 machine learning 的时候不是有 L1/L2 的regularization。这一项也很像 regularization这样 regularization 做的事情就是希望最后 learn 出来的 $\theta$ 不要跟 $\theta'$ 太不一样
举个具体的例子来看看这些计算出来的是什么效果。这是一个悬崖问题。这个问题是需要智能体从这个出发点 S 出发,然后到达目的地 G同时避免掉进悬崖(cliff),掉进悬崖的话就会有负一百分的惩罚,而且不会结束游戏,它会被直接拖回那个起点,游戏继续。为了到达目的地的话,我们可以沿着蓝线和红线走
PPO 有一个前身叫做TRPOTRPO 的式子如下式所示。
$$
\begin{aligned}
J_{T R P O}^{\theta^{\prime}}(\theta)=E_{\left(s_{t}, a_{t}\right) \sim \pi_{\theta^{\prime}}}\left[\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{\prime}}\left(a_{t} | s_{t}\right)} A^{\theta^{\prime}}\left(s_{t}, a_{t}\right)\right] \\ \\
\mathrm{KL}\left(\theta, \theta^{\prime}\right)<\delta
\end{aligned}
$$
它与PPO不一样的地方 是 constrain 摆的位置不一样PPO是直接把 constrain 放到你要 optimize 的那个式子里面,然后你就可以用 gradient ascent 的方法去 maximize 这个式子。但 TRPO 是把 KL divergence 当作constrain它希望 $\theta$ 跟 $\theta'$ 的 KL divergence 小于一个$\delta$。如果你是用 gradient based optimization 时,有 constrain 是很难处理的。
PPO是很难处理的因为它是把 KL divergence constrain 当做一个额外的 constrain没有放 objective 里面,所以它很难算。所以不想搬石头砸自己的脚的话, 你就用PPO 不要用TRPO。看文献上的结果是PPO 跟TRPO 可能 performance 差不多,但 PPO 在实现上比 TRPO 容易的多。
KL divergence 到底指的是什么?这边我是直接把 KL divergence 当做一个 functioninput 是 $\theta$ 跟 $\theta'$,但我的意思并不是说把 $\theta$ 或 $\theta'$ 当做一个distribution算这两个distribution 之间的距离,我不是这个意思。所谓的 $\theta$ 跟 $\theta'$ 的距离并不是参数上的距离,而是 behavior 上的距离。
假设你有一个model有一个actor 它是$\theta$你有另外一个actor 的参数是$\theta'$ ,所谓参数上的距离就是你算这两组参数有多像。我今天所讲的不是参数上的距离, 而是它们行为上的距离。就是你先带进去一个state s它会对这个 action 的 space output 一个 distribution。假设你有 3 个actions3 个可能的 actions 就 output 3 个值。那今天所指的 distance 是behavior distance。也就是说给同样的 state 的时候,输出 action 之间的差距。这两个 actions 的 distribution 都是一个概率分布。所以就可以计算这两个概率分布的 KL divergence。把不同的 state output 的这两个 distribution 的KL divergence 平均起来才是我这边所指的两个 actor 间的 KL divergence。你可能说怎么不直接算这个 $\theta$ 或 $\theta'$ 之间的距离甚至不要用KL divergence 算L1 跟 L2 的 norm 也可以保证 $\theta$ 跟 $\theta'$ 很接近啊。在做reinforcement learning 的时候,之所以我们考虑的不是参数上的距离,而是 action 上的距离,是因为很有可能对 actor 来说,参数的变化跟 action 的变化不一定是完全一致的。有时候你参数小小变了一下,它可能 output 的行为就差很多。或是参数变很多,但 output 的行为可能没什么改变。**所以我们真正在意的是这个actor 它的行为上的差距,而不是它们参数上的差距。**所以在做PPO 的时候,所谓的 KL divergence 并不是参数的距离而是action 的距离。
![](img/2.8.png)
我们来看一下PPO1 的algorithm。它先initial 一个policy 的参数$\theta^0$。然后在每一个iteration 里面呢,你要用参数$\theta^k$$\theta^k$ 就是你在前一个training 的iteration得到的actor 的参数,你用$\theta^k$ 去跟环境做互动sample 到一大堆 state-action 的pair
在这个环境当中,我们去怎么去计算状态动作价值,就是未来的总收益的话。假设我走一条路,然后这条路的话,我从这个状态出发,在这里选择是向上,这里选择向右,选择向右
然后你根据$\theta^k$ 互动的结果,估测一下$A^{\theta^{k}}\left(s_{t}, a_{t}\right)$。然后你就 apply PPO 的 optimization 的 formulation。但跟原来的policy gradient 不一样,原来的 policy gradient 只能 update 一次参数update 完以后,你就要重新 sample data。但是现在不用你拿 $\theta^k$ 去跟环境做互动sample 到这组 data 以后,你可以让 $\theta$ update 很多次,想办法去 maximize objective function。这边 $\theta$ update 很多次没有关系,因为我们已经有做 importance sampling所以这些experience这些 state-action 的 pair 是从 $\theta^k$ sample 出来的没有关系。$\theta$ 可以 update 很多次,它跟 $\theta^k$ 变得不太一样也没有关系,你还是可以照样训练 $\theta$
如果 $\gamma = 0$,然后用这个公式去计算的话,它相当于考虑的就是一个单步的收益。我们可以认为它是一个目光短浅的一个计算的方法
但 $\gamma = 1$ 的话,那就等于是说把后续所有的收益可能都全部加起来。在这里悬崖问题,你每走一步都会拿到一个 -1 分的 reward。只有到了终点之后它才会停止。如果说 $\gamma =1 $的话,我们用这个公式去计算,就这里是 -1。然后这里的话未来的总收益就是 $-1+-1=-2$ ,这样子去计算。
如果说折中一下,让 $\gamma = 0.6$ 话,那就是目光没有放得那么的长远,计算出来是这个样子的。
利用 $G_{t}=R_{t+1}+\gamma G_{t+1}$ 这个公式从后往前推。
$$
\begin{array}{l}
G_{7}=R+\gamma G_{8}=-1+0.6 *(-2.176)=-2.3056 \approx-2.3 \\
G_{8}=R+\gamma G_{9}=-1+0.6 *(-1.96)=-2.176 \approx-2.18 \\
G_{9}=R+\gamma G_{10}=-1+0.6 *(-1.6)=-1.96 \\
G_{10}=R+\gamma G_{11}=-1+0.6 *(-1)=-1.6 \\
G_{12}=R+\gamma G_{13}=-1+0.6 * 0=-1 \\
G_{13}=0
\end{array}
$$
这里的计算是我们选择了一条路,走完这条路径上每一个状态动作的价值,我们可以看一下右下角这个图,如果说我走的不是这条路,我走的是这一条路,那我算出来那个状态动作价值的 Q 值可能是这样。那我们就知道,当小乌龟在 -12 这个点的时候,往右边走是 -11往上走是 -15。它自然就知道往右走的价值更大小乌龟就会往右走
![](img/2.9.png)
最后我们要求解的就是类似于这样子的一张 Q表格。就是它的行数是所有的状态数量一般可以用坐标来表示表示格子的状态也可以用 1、2、3、4、5、6、7 来表示不同的位置。那一共四列的话就代表说是上下左右四个动作。最开始这张 Q 表格会全部初始化为零,然后在 agent 不断地去和环境交互得到不同的轨迹,当交互的次数足够多的时候,我们就可以估算出每一个状态下,每个行动的平均总收益去更新这个 Q 表格。怎么去更新 Q 表格就是我们接下来要引入的强化学习的强化概念。
在PPO 的paper 里面还有一个 `adaptive KL divergence`,这边会遇到一个问题就是 $\beta$ 要设多少它就跟那个regularization 一样。regularization 前面也要乘一个weight所以这个 KL divergence 前面也要乘一个 weight但 $\beta$ 要设多少呢?所以有个动态调整 $\beta$ 的方法。在这个方法里面,你先设一个 KL divergence你可以接受的最大值。然后假设你发现说你 optimize 完这个式子以后KL divergence 的项太大,那就代表说后面这个 penalize 的 term 没有发挥作用,那就把 $\beta$ 调大。那另外你定一个 KL divergence 的最小值。如果发现 optimize 完上面这个式子以后KL divergence 比最小值还要小,那代表后面这一项的效果太强了,你怕他只弄后面这一项,那$\theta$ 跟$\theta^k$ 都一样,这不是你要的,所以你这个时候你叫要减少 $\beta$。所以 $\beta$ 是可以动态调整的。这个叫做 adaptive KL penalty
强化概念的就是我们可以用下一个状态的价值来更新当前状态的价值。其实就是强化学习里面有一个bootstrap(自助)的概念。在强化学习里面,你可以每走一步更新一下 Q 表格,然后用下一个状态的 Q 值来更新这个状态的 Q 值
![](img/2.10.png)
如果你觉得算 KL divergence 很复杂。有一个PPO2。PPO2 要去 maximize 的 objective function 如下式所示,它的式子里面就没有 KL divergence
$$
\begin{aligned}
J_{P P O 2}^{\theta^{k}}(\theta) \approx \sum_{\left(s_{t}, a_{t}\right)} \min &\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)} A^{\theta^{k}}\left(s_{t}, a_{t}\right),\right.\\
&\left.\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right) A^{\theta^{k}}\left(s_{t}, a_{t}\right)\right)
\end{aligned}
$$
这个式子看起来有点复杂,但实际 implement 就很简单。我们来实际看一下说这个式子到底是什么意思。
min 这个 operator 做的事情是第一项跟第二项里面选比较小的那个。第二项前面有个clip functionclip 这个function 的意思是说在括号里面有3 项如果第一项小于第二项的话那就output $1-\varepsilon$ 。第一项如果大于第三项的话那就output $1+\varepsilon$。 $\varepsilon$ 是一个 hyper parameter你要tune 的,你可以设成 0.1 或 设 0.2 。
假设这边设0.2 的话,如下式所示
$$
\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 0.8, 1.2\right)
$$
如果$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$算出来小于0.8那就当作0.8。如果算出来大于1.2那就当作1.2。
我们先看一下下面这项这个算出来到底是什么的东西。
$$
\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right)
$$
这种单步更新的方法是我们在强化学习里面会接触到的叫`时序差分`的更新方法。为了让大家更好理解强化学习里面时序差分的这种更新方法。我这里就找了一下它的的物理意义。我们先理解一下巴普洛夫的条件反射实验了。这个实验讲的是什么呢?就是小狗对盆里面的食物,它会产生无条件刺激分泌唾液。一开始小狗对于铃声这种中性刺激是没有反应的。可是我们把这个铃声和这个食物结合起来,每次先给它响一下铃,再给它喂食物。多次重复之后,当铃声响起的时候,小狗也会开始流口水。盆里的肉可以认为是强化学习里面最后面的那个延迟的那个 reward。声音的刺激可以认为是有 reward 的那个状态之前的一个状态。多次重复实验之后,最后的这个 reward 会强化小狗对于这个声音的条件反射,它会让小狗知道说这个声音代表着有食物,这个声音对于小狗来说也就有了价值,它听到这个声音也会也会流口水
![](img/2.11.png)
上图的横轴是 $\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$,纵轴是 clip function 实际的输出
巴普洛夫效应揭示的是中性刺激(铃声)跟无条件刺激(食物)紧紧挨着反复出现的时候,条件刺激也可以引起无条件刺激引起的唾液分泌,然后形成这个条件刺激。这种中性刺激跟无条件刺激在时间上面的结合,我们就称之为强化。 强化的次数越多,那条件反射就会越巩固,那就是小狗原本不觉得铃声有价值的,经过强化之后,小狗就会慢慢地意识到铃声也是有价值的,它可能带来带来食物。更重要是一种条件反射巩固之后,我们再用另外一种新的刺激和条件反射去结合,还可以形成第二级条件反射,同样还可以形成第三级条件反射。在人的身上是可以建立多级的条件反射的。举个例子,比如说一般我们遇到熊都是这样一个顺序,看到树上有熊瓜,然后看到熊之后,突然熊发怒,扑过来了。经历这个过程之后,我们可能最开始看到熊才会瑟瑟发抖,后面就是看到树上有熊爪就已经有害怕的感觉了。也就说在不断的重复试验之后,下一个状态的价值,它是可以不断地去强化影响上一个状态的价值的
* 如果 $\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$ 大于$1+\varepsilon$,输出就是$1+\varepsilon$。
* 如果小于 $1-\varepsilon$ 它输出就是 $1-\varepsilon$。
* 如果介于 $1+\varepsilon$ 跟 $1-\varepsilon$ 之间, 就是输入等于输出。
![](img/2.12.png)
$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$ 是绿色的线,$\operatorname{clip}\left(\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}, 1-\varepsilon, 1+\varepsilon\right)$ 是蓝色的线。在绿色的线跟蓝色的线中间,我们要取一个最小的。假设前面乘上的这个 term A它是大于0 的话,取最小的结果,就是红色的这一条线
为了让大家更加直观感受一下这个下一个状态影响上一个状态效果,这里推荐那个斯坦福大学的一个网站[Temporal Difference Learning Gridworld Demo](https://cs.stanford.edu/people/karpathy/reinforcejs/gridworld_td.html)。这个网站模拟了就是这种单步更新的过程中,所有格子的一个状态价值的变化过程。我们可以看到格子里面有几个 -1的 reward。只有一个 +1 reward 的那个格子
![](img/2.13.png)
如果 A 小于0 的话,取最小的以后,就得到红色的这一条线
这一个式子虽然看起来有点复杂implement 起来是蛮简单的,因为这个式子想要做的事情就是希望 $p_{\theta}(a_{t} | s_{t})$ 跟$p_{\theta^k}(a_{t} | s_{t})$,也就是你拿来做 demonstration 的那个model 跟你实际上 learn 的 model在optimize 以后不要差距太大。那你要怎么让它做到不要差距太大呢?
玩起来是这样的,先初始化一下,然后开始时序差分的更新过程,训练的过程你会看到这个小黄球不断的在试错。但探索当中会先迅速地发现有 reward的地方。最开始的时候只是这些有 reward 的格子 才有价值,当不断的重复走这些路线的时候,这些有价值的格子,它可以去慢慢的影响它附近的格子的价值。反复训练之后,有 reward 的这些格子周围的格子的状态就会慢慢的被强化,然后强化就是当它收敛到最后一个最优的状态了,就是把这些价值最终收敛到一个最优的情况之后,那个小黄球就会自动地知道,就是我一直往价值高的地方走,我就能够走到能够拿到 reward 的地方
如果 A 大于 0也就是某一个 state-action 的pair 是好的。那我们希望增加这个state-action pair 的概率。也就是说,我们想要让 $p_{\theta}(a_{t} | s_{t})$ 越大越好,但它跟 $p_{\theta^k}(a_{t} | s_{t})$ 的比值不可以超过 $1+\varepsilon$。如果超过$1+\varepsilon$ 的话就没有benefit 了。红色的线就是我们的objective function我们希望objective 越大越好,我们希望 $p_{\theta}(a_{t} | s_{t})$ 越大越好。但是$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$只要大过 $1+\varepsilon$就没有benefit 了。
所以今天在train 的时候,当$p_{\theta}(a_{t} | s_{t})$ 被 train 到$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$大于 $1+\varepsilon$ 时,它就会停止。
假设 $p_{\theta}(a_{t} | s_{t})$ 比 $p_{\theta^k}(a_{t} | s_{t})$ 还要小,那我们的目标是要让 $p_{\theta}(a_{t} | s_{t})$ 越大越好。
* 假设这个 advantage 是正的,我们希望$p_{\theta}(a_{t} | s_{t})$ 越大越好。假设这个 action 是好的,我们当然希望这个 action 被采取的概率越大越好。所以假设 $p_{\theta}(a_{t} | s_{t})$ 还比 $p_{\theta^k}(a_{t} | s_{t})$ 小,那就尽量把它挪大,但只要大到$1+\varepsilon$ 就好。
* 负的时候也是一样如果某一个state-action pair 是不好的,我们希望把 $p_{\theta}(a_{t} | s_{t})$ 减小。如果 $p_{\theta}(a_{t} | s_{t})$ 比$p_{\theta^k}(a_{t} | s_{t})$ 还大,那你就尽量把它压小,压到$\frac{p_{\theta}\left(a_{t} | s_{t}\right)}{p_{\theta^{k}}\left(a_{t} | s_{t}\right)}$是$1-\epsilon$ 的时候就停了,就不要再压得更小。
这样的好处就是, 你不会让 $p_{\theta}(a_{t} | s_{t})$ 跟 $p_{\theta^k}(a_{t} | s_{t})$ 差距太大。要 implement 这个东西,很简单。
![](img/2.14.png)
上图是 PPO 跟其它方法的比较。Actor-Critic 和 A2C+Trust Region 方法是actor-critic based 的方法。PPO 是紫色线的方法这边每张图就是某一个RL 的任务你会发现说在多数的cases 里面PPO 都是不错的,不是最好的,就是第二好的。
这种强化方式其实在数学上面一行公式就表达出来了。我们也喊说这种更新的方式叫做时序差分的一个更新的方式。这个公式它想要表达就是我可以拿下一步的Q 值 $Q(S_{t+_1},A_{t+1})$ 来更新我这一步的 Q 值 $Q(S_t,A_t)$ 。
为了理解这个公式,如图所示,我们先把这一块当作是一个目标值,就是 $Q(S_t,A_t)$ 想要去逼近的一个目标值。我们想要计算的就是这个 $Q(S_t,A_t)$ 。因为最开始Q值都是随机初始化或者是初始化为零。它需要不断的去逼近它理想中真实的Q 值,我们就叫 target 。Target 就是未来收益的总和大概是有多少,而且是带衰减的那个。
我们用 $G_t$ 来表示未来收益总和(return),我们对 return 做一下简单的数学变化,然后我们可以知道
$$
G_t = R_{t+1}+ \gamma G_{t+1}
$$
也就是说,我们拿 $Q(S_t,A_t)$ 来逼近这个 $G_t$ , 那 $Q(S_{t+1},A_{t+1})$ 其实就是近似这个 $G_{t+1}$ ,那我们可以把 $G_{t+1}$ 放到这个目标值这里。$Q(S_t,A_t)$ 就是要逼近这个目标值,怎么去逼近了。我们用软更新的方式。
软更新的方式就是 $\alpha$ ,每次我只更新一点点。这个 $\alpha$ 有点类似于像学习率一样的东西。最终的话Q 值都是可以慢慢地逼近到真实的 target 值的。这样我们的更新公式只需要用到当前时刻的 $S_{t},A_t$ ,然后还有拿到的 $R_{t+1}, S_{t+1}A_{t+1}$ 。
我们只需要这几个值,就是$(S_{t}, A_{t}, R_{t+1}, S_{t+1}, A_{t+1})$ ,这就是 Sarsa 算法。它的命名其实就是因为它用到的就是这几个值。因为它走了一步之后,它拿到了 $(S_{t}, A_{t}, R_{t+1}, S_{t+1}, A_{t+1})$ 之后,它就可以做一次这样子的更新。
![](img/2.15.png)
然后知关于就是用那个巴甫洛夫效应来去理解的公式的也是在强化学习那本书名第14章有提到过了。大家感兴趣可以再去读一读了解一下。
我们看看用代码去怎么去实现。了解单步更新的一个基本公式之后,代码实现就很简单了。这个是环境,这个是 agent 。我们每次跟环境交互一次之后呢,就可以 learn 一下。我们向环境输出 action
然后从环境当中拿到那 state 和 reward。Agent 主要实现两个方法,一个就是根据 Q 表格去选择动作输出action。另外一个就是拿到 $(S_{t}, A_{t}, R_{t+1}, S_{t+1}, A_{t+1})$ 这几个值去更新我们的 Q 表格。
![](img/2.16.png)我们直接看这个框框里面的更新公式, 和之前的公式是一模一样的。$S'$ 就是 $S_{t+1}$ 。我们就是拿下一步的 Q 值来更新这一步的 Q 值,不断地强化每一个 Q。
## Q-learning
![](img/2.17.png)
Sarsa 是一种 on-policy 策略。Sarsa 优化的是它实际执行的策略。它直接拿下一步,我一定会执行的 action 来去优化我的 Q 表格,所以 on-policy 在学习的过程中,只存在一种策略,它用一种策略去做 action 的选取,也用一种策略去做优化。所以 Sarsa 知道它下一步的动作有可能会跑到悬崖那边去,所以它就会在优化它自己的策略的时候,它会尽可能的离悬崖远一点哦。那这样子就会保证说,它下一步哪怕是有随机动作,它也还是在安全区域内。
而 off-policy 在学习的过程中,保留了两种不同的策略。第一个策略是我们希望学到一个最佳的目标策略,另外一个策略是探索环境的策略。它可以大胆地去探索到所有可能的轨迹,然后喂给这个目标策略去学习。而且喂给目标策略的数据中并不需要 $a_{t+1}$ 。注意Sarsa 是有 $a_{t+1}$ 的。它喂给目标策略的数据不需要 $a_{t+1}$,比如说目标策略优化时候,它才不管你下一步去往哪里探索,会不会掉悬崖,我就只选我收益最大一个最优的策略。探索环境的策略,我们叫做 `behavior policy`,它像是一个天不怕地不怕的一个前线的战士,可以在环境里面探索所有的动作和轨迹和经验。然后把这些经验的交给目标策略去学习。目标策略就像是在后方指挥战术的一个军师,它可以根据自己的经验来学习最优的策略,它不需要去和环境交互。
![](img/2.18.png)
Q-learning 是 off-policy 的Sarsa 是 on-policy 的。 我们通过对比的方式来去理解 Q-learning。Sarsa 在更新 Q 表格的时候,它用到的 A' 。我要获取下一个 Q 值的时候,我用到了的 A' 是下一个 step 一定会执行的 action 。这个也 action 有可能是 $\varepsilon$-greddy 方法 sample 出来的值,也有可能是 max Q 对应的 action也有可能是随机动作。但是就是它实实在在执行了的那个动作。
但是 Q-learning 在更新 Q 表格的时候,它用到这个的 Q 值 $Q(S',a')$ 对应的那个 action ,它不一定是下一个 step 会执行的实际的 action因为你下一个实际会执行的那个 action 可能会探索。Q-learning 默认的 action 不是通过 behavior policy 来选取的,它是默认 A' 为最优策略选的动作,所以 Q-learning 在学习的时候不需要传入A',即 $a_{t+1}$ 的值。
![](img/2.19.png)
我们再仔细地对比一下两个更新公式,它们俩的更新公式都是一样的。区别只在 target 计算的这一部分。Sarsa 是 $R_{t+1}+\gamma Q(S_{t+1}, A_{t+1})$ Q-learning 是$R_{t+1}+\gamma \underset{a}{\max} Q\left(S_{t+1}, a\right)$ 。
Sarsa 实际上都是用自己的策略产生了 S,A,R,S',A' 这一条轨迹。然后拿着 $Q(S_{t+1},A_{t+1})$ 去更新原本的Q值 $Q(S_t,A_t)$。 但是 Q-learning 并不需要知道,我实际上选择哪一个 action ,它默认下一个动作就是 Q 最大的那个动作。所以它知道实际上 behavior policy 可能会有 10% 的概率去选择别的动作,但是 Q-learning 并不担心受到探索的影响,它默认了就按照最优的策略来去优化我的目标策略,所以它可以更大胆地去寻找最优的路径,它其实会表现的比 Sarsa 大胆非常多。
然后Q-learning 的这个逐步的一个拆解的话跟Sarsa 唯一一点不一样就是我并不需要提前知道我 $A_2$ ,我就能更新 $Q(S_1,A_1)$ 。在训练一个 episode 这个流程图当中Q-leanring 在 learn 之前它也不需要去拿到 next action A',它只需要前面四个 $(S,A,R,S')$也就可以了。这一点就是跟 Sarsa 有一个很明显的区别。
![](img/2.20.png)
下面我讲一下 on-policy 和 off-policy 的区别。
Sarsa 就是一个典型的 on-policy 策略,它只用一个 $\pi$ 为了兼顾探索和利用所以它训练的时候会显得有一点点胆小怕事。它在解决悬崖问题的时候会尽可能地离悬崖边上远远的确保说哪怕自己不小心探索了一点了也还是在安全区域内不不至于跳进悬崖。Q-leanring 是一个比较典型的 off-policy 的策略,它有目标策略 target policy一般用 $\pi$ 来表示。然后还有行为策略 behavior policy用 $\mu$ 来表示。它分离了目标策略跟行为策略。Q-learning 就可以大胆的用 behavior policy 去探索得到的经验轨迹来去优化我的目标策略。这样子我更有可能去探索到最优的策略。
![](img/2.21.png)
总结如上图所示。

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 456 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 965 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 335 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 645 KiB

After

Width:  |  Height:  |  Size: 335 KiB

BIN
docs/chapter2/img/2.15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

BIN
docs/chapter2/img/2.16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 520 KiB

BIN
docs/chapter2/img/2.17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

BIN
docs/chapter2/img/2.18.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 KiB

BIN
docs/chapter2/img/2.19.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 494 KiB

BIN
docs/chapter2/img/2.20.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB

BIN
docs/chapter2/img/2.21.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 KiB

After

Width:  |  Height:  |  Size: 283 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 KiB

After

Width:  |  Height:  |  Size: 390 KiB

View File

@@ -1,311 +1,240 @@
# Q-learning
## Q-learning
# Policy Gradient
## Policy Gradient
![](img/3.1.png)
Q-learning 是 `value-based` 的方法。在 value based 的方法里面,我们 learn 的不是 policy我们要 learn 的是一个 `critic`。Critic 并不直接采取行为,它想要做的事情是评价现在的行为有多好或是有多不好。假设有一个 actor $\pi$ critic 的工作就是来评价这个 actor 的 policy $\pi$ 好还是不好,即 `Policy Evaluation(策略评估)`
在 reinforcement learning 中有 3 个components一个`actor`,一个`environment`,一个`reward function`
举例来说,有一种 critic 叫做 `state value function`。State value function 的意思就是说,假设 actor 叫做 $\pi$,拿 $\pi$ 跟环境去做互动。假设 $\pi$ 看到了某一个state s如果在玩 Atari 游戏的话state s 是某一个画面,看到某一个画面的时候,接下来一直玩到游戏结束,累积的 reward 的期望值有多大。所以 $V^{\pi}$ 是一个function这个 function input 一个 state然后它会 output 一个 scalar。这个 scalar 代表说,$\pi$ 这个 actor 看到 state s 的时候,接下来预期到游戏结束的时候,它可以得到多大的 value。
让机器玩 video game 时,
举个例子,假设你是玩 space invader 的话,
* actor 做的事情就是去操控游戏的摇杆, 比如说向左、向右、开火等操作;
* environment 就是游戏的主机, 负责控制游戏的画面负责控制说,怪物要怎么移动, 你现在要看到什么画面等等;
* reward function 就是当你做什么事情,发生什么状况的时候,你可以得到多少分数, 比如说杀一只怪兽得到 20 分等等。
* 左边这个 state s这一个游戏画面你的 $V^{\pi}(s)$ 也许会很大,因为还有很多的怪可以杀, 所以你会得到很大的分数。一直到游戏结束的时候,你仍然有很多的分数可以吃。
* 右边那个case也许你得到的 $V^{\pi}(s)$ 就很小,因为剩下的怪也不多了,并且红色的防护罩已经消失了,所以可能很快就会死掉。所以接下来得到预期的 reward就不会太大。
同样的概念用在围棋上也是一样的,
这边需要强调的一个点是说,当你在讲这一个 critic 的时候critic 都是绑一个 actor 的critic 没有办法去凭空去 evaluate 一个 state 的好坏,它所 evaluate 的东西是在给定某一个 state 的时候, 假设接下来互动的 actor 是 $\pi$,那我会得到多少 reward。因为就算是给同样的 state你接下来的 $\pi$ 不一样,你得到的 reward 也是不一样的。举例来说在左边那个case虽然假设是一个正常的 $\pi$,它可以杀很多怪,那假设他是一个很弱的 $\pi$,它就站在原地不动,然后马上就被射死了,那你得到的 V 还是很小。所以 critic output 值有多大其实是取决于两件事state 和 actor。所以你的 critic 其实都要绑一个 actor它是在衡量某一个 actor 的好坏,而不是 generally 衡量一个 state 的好坏。这边要强调一下critic output 是跟 actor 有关的state value 其实是 depend on 你的 actor。当你的 actor 变的时候state value function 的output 其实也是会跟着改变的。
* actor 就是 alpha Go它要决定下哪一个位置
* environment 就是对手;
* reward function 就是按照围棋的规则, 赢就是得一分,输就是负一分等等。
再来问题就是,怎么衡量这一个 state value function 呢?怎么衡量这一个$V^{\pi}(s)$ 呢?有两种不同的做法
在 reinforcement learning 里面environment 跟 reward function 不是你可以控制的environment 跟 reward function 是在开始学习之前,就已经事先给定的。你唯一能做的事情是调整 actor 里面的 policy使得 actor 可以得到最大的 reward。Actor 里面会有一个 policy 这个policy 决定了actor 的行为。Policy 就是给一个外界的输入,然后它会输出 actor 现在应该要执行的行为
![](img/3.2.png)
**Policy 一般写成 $\pi$**。假设你是用 deep learning 的技术来做 reinforcement learning 的话,**policy 就是一个 network**。Network 里面就有一堆参数, 我们用 $\theta$ 来代表 $\pi$ 的参数。Network 的 input 就是现在 machine 看到的东西,如果让 machine 打电玩的话, 那 machine 看到的东西就是游戏的画面。Machine 看到什么东西,会影响你现在 training 到底好不好 train。
怎么 estimate 这些critic那怎么 estimate $V^{\pi}(s)$ 呢。有两个方向,一个是用` Monte-Carlo(MC) based` 的方法。MC based 的方法就是让 actor 去跟环境做互动,你要看 actor 好不好, 你就让 actor 去跟环境做互动给critic 看。然后critic 就统计说actor 如果看到 state $s_a$,接下来 accumulated reward 会有多大。如果它看到 state $s_b$接下来accumulated reward 会有多大。但是实际上你当然不可能把所有的state 通通都扫过。如果你是玩 Atari 游戏的话,你的 state 是 image 你没有办法把所有的state 通通扫过。所以实际上我们的 $V^{\pi}(s)$ 是一个network。对一个network 来说,就算是 input state 是从来都没有看过的,它也可以想办法估测一个 value 的值
举例来说,在玩游戏的时候, 也许你觉得游戏的画面,前后是相关的,也许你觉得说,你应该让你的 policy看从游戏初始到现在这个时间点所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子,你会比较难处理。要让你的 machine你的 policy 看到什么样的画面, 这个是你自己决定的。让你知道说给机器看到什么样的游戏画面可能是比较有效的。Output 的就是今天机器要采取什么样的行为
怎么训练这个 network 呢因为如果在state $s_a$,接下来的 accumulated reward 就是 $G_a$。也就是说,对这个 value function 来说,如果 input 是 state $s_a$,正确的 output 应该是$G_a$。如果 input state $s_b$正确的output 应该是value $G_b$。所以在 training 的时候, 它就是一个 `regression problem`。Network 的 output 就是一个 value你希望在 input $s_a$ 的时候output value 跟 $G_a$ 越近越好input $s_b$ 的时候output value 跟 $G_b$ 越近越好。接下来把 network train 下去就结束了。这是第一个方法MC based 的方法。
上图就是具体的例子,
* policy 就是一个 network
* input 就是游戏的画面,它通常是由 pixels 所组成的;
* output 就是看看说有那些选项是你可以去执行的output layer 就有几个 neurons。
假设你现在可以做的行为就是有 3 个output layer 就是有 3 个 neurons。每个 neuron 对应到一个可以采取的行为。Input 一个东西后network 就会给每一个可以采取的行为一个分数。接下来,你把这个分数当作是概率。 actor 就是看这个概率的分布,根据这个机率的分布,决定它要采取的行为。比如说 70% 会走 left20% 走 right10% 开火等等。概率分布不同actor 采取的行为就会不一样。
![](img/3.3.png)
接下来用一个例子来说明 actor 是怎么样跟环境互动的。 首先 actor 会看到一个游戏画面,我们用 $s_1$ 来表示这个游戏画面,它代表游戏初始的画面。接下来 actor 看到这个游戏的初始画面以后,根据它内部的 network根据它内部的 policy 来决定一个 action。假设它现在决定的 action 是向右,它决定完 action 以后,它就会得到一个 reward ,代表它采取这个 action 以后得到的分数。
第二个方法是`Temporal-difference(时序差分)` 的方法, `即 TD based ` 的方法。在 MC based 的方法中,每次我们都要算 accumulated reward也就是从某一个 state $s_a$ 一直玩到游戏结束的时候得到的所有reward 的总和。所以你要 apply MC based 的 approach你必须至少把这个游戏玩到结束。但有些游戏非常的长你要玩到游戏结束才能够 update network你可能根本收集不到太多的资料花的时间太长了。所以我们会采用 TD based 的方法。TD based 的方法不需要把游戏玩到底,只要在游戏的某一个情况,某一个 state $s_t$ 的时候,采取 action $a_t$ 得到 reward $r_t$ ,跳到 state $s_{t+1}$,就可以 apply TD 的方法
怎么 apply TD 的方法呢?这边是基于以下这个式子:
$$
V^{\pi}\left(s_{t}\right)=V^{\pi}\left(s_{t+1}\right)+r_{t}
$$
假设我们现在用的是某一个 policy $\pi$,在 state $s_t$,它会采取 action $a_t$,给我们 reward $r_t$ ,接下来进入$s_{t+1}$ 。state $s_{t+1}$ 的 value 跟 state $s_t$ 的 value它们的中间差了一项 $r_t$。因为你把 $s_{t+1}$ 得到的 value 加上得到的 reward $r_t$ 就会等于 $s_t$ 得到的 value。有了这个式子以后你在 training 的时候,你并不是直接去估测 V而是希望你得到的结果 V 可以满足这个式子。也就是说你会是这样 train 的,你把 $s_t$ 丢到 network 里面,因为 $s_t$ 丢到 network 里面会得到 $V^{\pi}(s_t)$,把 $s_{t+1}$ 丢到你的 value network 里面会得到$V^{\pi}(s_{t+1})$,这个式子告诉我们,$V^{\pi}(s_t)$ 减 $V^{\pi}(s_{t+1})$ 的值应该是 $r_t$。然后希望它们两个相减的 loss 跟 $r_t$ 越接近train 下去update V 的参数,你就可以把 V function learn 出来。
我们把一开始的初始画面,写作 $s_1$ 把第一次执行的动作叫做 $a_1$,把第一次执行动作完以后得到的 reward 叫做 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$这个都可以你自己看得懂就好。Actor 决定一个的行为以后, 就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给 actor这个 actor 决定要开火,然后它可能杀了一只怪,就得到五分。然后这个 process 就反复地持续下去,直到今天走到某一个 timestamp 执行某一个 action得到 reward 之后, 这个 environment 决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了
![](img/3.4.png)
MC 跟 TD 有什么样的差别呢?**MC 最大的问题就是 variance 很大**。因为我们在玩游戏的时候,它本身是有随机性的。所以你可以把 $G_a$ 看成一个 random 的 variable。因为你每次同样走到 $s_a$ 的时候,最后你得到的 $G_a$ 其实是不一样的。你看到同样的state $s_a$,最后玩到游戏结束的时候,因为游戏本身是有随机性的,玩游戏的 model 搞不好也有随机性,所以你每次得到的 $G_a$ 是不一样的,每一次得到$G_a$ 的差别其实会很大。为什么它会很大呢?因为 $G_a$ 其实是很多个不同的 step 的 reward 的和。假设你每一个step 都会得到一个reward$G_a$ 是从 state $s_a$ 开始一直玩到游戏结束每一个timestamp reward 的和。
举例来说,我在右上角就列一个式子是说,
$$
\operatorname{Var}[k X]=k^{2} \operatorname{Var}[X]
$$
Var 就是指 variance。
通过这个式子,我们知道 $G_a$ 的 variance 相较于某一个 state 的 reward它会是比较大的$G_a$ 的variance 是比较大的。
现在如果说用TD 的话呢?用 TD 的话,你是要去 minimize 这样的一个式子:
一场游戏叫做一个 `Episode`。把这个游戏里面,所有得到的 reward 都总合起来,就是 `Total reward`,我们称其为`Return(回报)`,用 R 来表示它。Actor 存在的目的就是想办法去 maximize 它可以得到的 reward。
![](img/3.5.png)
首先,`environment` 是一个`function`,游戏的主机也可以把它看作是一个 function虽然它不一定是 neural network可能是 rule-based 的规则,但你可以把它看作是一个 function。这个 function一开始就先吐出一个 state也就是游戏的画面接下来你的 actor 看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 environment 把 $a_1$ 当作它的输入,然后它再吐出 $s_2$吐出新的游戏画面。Actor 看到新的游戏画面,再采取新的行为 $a_2$,然后 environment 再看到 $a_2$,再吐出 $s_3$。这个 process 会一直持续下去,直到 environment 觉得说应该要停止为止。
在一场游戏里面,我们把 environment 输出的 $s$ 跟 actor 输出的行为 $a$,把这个 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory`,如下式所示。
$$
\text { Trajectory } \tau=\left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\}
$$
每一个 trajectory你可以计算它发生的概率。假设现在 actor 的参数已经被给定了话,就是 $\theta$。根据 $\theta$,你其实可以计算某一个 trajectory 发生的概率,你可以计算某一个回合,某一个 episode 里面, 发生这样子状况的概率。
$$
\begin{aligned}
p_{\theta}(\tau)
&=p\left(s_{1}\right) p_{\theta}\left(a_{1} | s_{1}\right) p\left(s_{2} | s_{1}, a_{1}\right) p_{\theta}\left(a_{2} | s_{2}\right) p\left(s_{3} | s_{2}, a_{2}\right) \cdots \\
&=p\left(s_{1}\right) \prod_{t=1}^{T} p_{\theta}\left(a_{t} | s_{t}\right) p\left(s_{t+1} | s_{t}, a_{t}\right)
\end{aligned}
$$
怎么算呢,如上式所示。在假设你 actor 的参数就是 $\theta$ 的情况下,某一个 trajectory $\tau$ 的概率就是这样算的,你先算 environment 输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你 policy 里面的 network 参数 $\theta$ 所决定的, 它是一个概率,因为你的 policy 的 network 的 output 是一个 distributionactor 是根据这个 distribution 去做 sample决定现在实际上要采取的 action是哪一个。接下来 environment 根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟$s_1$ 还是有关系的,下一个游戏画面,跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在 actor 采取的行为 $a_1$,就会产生 $s_2$。
这件事情可能是概率,也可能不是概率,这个取决于 environment就是主机它内部设定是怎样。看今天这个主机在决定要输出什么样的游戏画面的时候有没有概率。因为如果没有概率的话这个游戏的每次的行为都一样你只要找到一条 path 就可以过关了,这样感觉是蛮无聊的 。所以游戏里面,通常是还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。Process 就反复继续下去,你就可以计算一个 trajectory $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。
**这个概率取决于两部分**
* 一部分是 `environment 的行为` environment 的 function 它内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是 environment environment 这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。
* 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$ actor 要采取什么样的 $a_t$ 会取决于你 actor 的参数 $\theta$ 所以这部分是 actor 可以自己控制的。随着 actor 的行为不同,每个同样的 trajectory 它就会有不同的出现的概率。
在这中间会有随机性的是 r。因为计算你在 $s_t$ 采取同一个 action你得到的 reward 也不一定是一样的,所以 r 是一个 random variable。但这个 random variable 的 variance 会比 $G_a$ 还要小,因为 $G_a$ 是很多 r 合起来,这边只是某一个 r 而已。$G_a$ 的 variance 会比较大r 的 variance 会比较小。但是这边你会遇到的**一个问题是你这个 V 不一定估得准**。假设你的这个 V 估得是不准的,那你 apply 这个式子 learn 出来的结果,其实也会是不准的。所以 MC 跟 TD各有优劣。**今天其实 TD 的方法是比较常见的MC 的方法其实是比较少用的。**
![](img/3.6.png)
上图是讲 TD 跟 MC 的差异。假设有某一个 critic它去观察某一个 policy $\pi$ 跟环境互动的 8 个 episode 的结果。有一个actor $\pi$ 跟环境互动了8 次得到了8 次玩游戏的结果。接下来这个 critic 去估测 state 的 value。
* 我们看看 $s_b$ 的 value 是多少。$s_b$ 这个state 在 8 场游戏里面都有经历过其中有6 场得到 reward 1有两场得到 reward 0所以如果你是要算期望值的话就看到 state $s_b$ 以后得到的 reward一直到游戏结束的时候得到的 accumulated reward 期望值是 3/4。
* 但 $s_a$ 期望的 reward 到底应该是多少呢这边其实有两个可能的答案一个是0一个是3/4。为什么有两个可能的答案呢这取决于你用MC 还是TD。用MC 跟用TD 算出来的结果是不一样的。
假如你用 MC 的话,你会发现这个$s_a$ 就出现一次,看到$s_a$ 这个state接下来 accumulated reward 就是 0。所以今天 $s_a$ expected reward 就是 0
在 reinforcement learning 里面,除了 environment 跟 actor 以外, 还有`reward function`。Reward function 根据在某一个 state 采取的某一个 action 决定说现在这个行为可以得到多少的分数。 它是一个 function给它 $s_1$$a_1$,它告诉你得到 $r_1$。给它 $s_2$ $a_2$,它告诉你得到 $r_2$。 把所有的 $r$ 都加起来,我们就得到了 $R(\tau)$ ,代表某一个 trajectory $\tau$ 的 reward。在某一场游戏里面 某一个 episode 里面,我们会得到 R。**我们要做的事情就是调整 actor 内部的参数 $\theta$ 使得 R 的值越大越好。** 但实际上 reward 并不只是一个 scalarreward 其实是一个 random variableR 其实是一个 random variable。 因为 actor 在给定同样的 state 会做什么样的行为这件事情是有随机性的。environment 在给定同样的 observation 要采取什么样的 action要产生什么样的 observation本身也是有随机性的。所以 R 是一个 random variable你能够计算的是它的期望值。你能够计算的是说在给定某一组参数 $\theta$ 的情况下,我们会得到的 R 的期望值是多少
但 TD 在计算的时候它要update 下面这个式子。
$$
V^{\pi}\left(s_{a}\right)=V^{\pi}\left(s_{b}\right)+r
\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)
$$
因为我们在 state $s_a$ 得到 reward r=0 以后,跳到 state $s_b$。所以 state $s_b$ 的 reward 会等于 state $s_b$ 的 reward 加上在state $s_a$ 跳到 state $s_b$ 的时候可能得到的 reward r。而这个得到的 reward r 的值是 0$s_b$ expected reward 是3/4那$s_a$ 的reward 应该是3/4。
用 MC 跟 TD 估出来的结果,其实很有可能是不一样的。就算 critic observed 到一样的 training data它最后估出来的结果。也不见得会是一样。那为什么会这样呢你可能问说那一个比较对呢其实就都对。
因为在第一个 trajectory $s_a$ 得到 reward 0 以后,再跳到 $s_b$ 也得到 reward 0。这边有两个可能。
* 一个可能是$s_a$,它就是一个带 sign 的 state所以只要看到 $s_a$ 以后,$s_b$ 就会拿不到reward有可能$s_a$ 其实影响了$s_b$。如果是用 MC 的算法的话,它会把 $s_a$ 影响 $s_b$ 这件事考虑进去。所以看到 $s_a$ 以后,接下来 $s_b$ 就得不到 reward所以看到$s_a$ 以后期望的reward 是 0。
* 另一个可能是,看到$s_a$ 以后, $s_b$ 的 reward 是0 这件事只是一个巧合,就并不是 $s_a$ 所造成,而是因为说 $s_b$ 有时候就是会得到 reward 0这只是单纯运气的问题。其实平常 $s_b$ 会得到 reward 期望值是3/4跟 $s_a$ 是完全没有关系的。所以假设 $s_a$ 之后会跳到 $s_b$,那其实得到的 reward 按照 TD 来算应该是3/4。
所以不同的方法考虑了不同的假设,运算结果不同。
这个期望值的算法如上式所示,穷举所有可能的 trajectory $\tau$ 每一个 trajectory $\tau$ 都有一个概率。比如 $\theta$ 是一个很强的 model 那它都不会死。如果有一个 episode 很快就死掉了, 它的概率就很小;如果有一个 episode 都一直没有死, 那它的概率就很大。根据你的 $\theta$ 你可以算出某一个 trajectory $\tau$ 出现的概率,接下来你计算这个 $\tau$ 的 total reward 是多少。 Total reward weighted by 这个 $\tau$ 出现的概率,对所有的 $\tau$ 进行求和,就是期望值。给定一个参数,你会得到的期望值。
$$
\bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=E_{\tau \sim p_{\theta}(\tau)}[R(\tau)]
$$
我们还可以写成上式那样,从 $p_{\theta}(\tau)$ 这个 distribution sample 一个 trajectory $\tau$,然后计算 $R(\tau)$ 的期望值,就是你的 expected reward。 我们要做的事情就是 maximize expected reward。
![](img/3.7.png)
怎么 maximize expected reward 呢?我们用的是 `gradient ascent`,因为要让它越大越好,所以是 gradient ascent。Gradient ascent 在 update 参数的时候要加。要进行 gradient ascent我们先要计算 expected reward $\bar{R}$ 的 gradient 。我们对 $\bar{R}$ 取一个 gradient这里面只有 $p_{\theta}(\tau)$ 是跟 $\theta$ 有关,所以 gradient 就放在 $p_{\theta}(\tau)$ 这个地方。$R(\tau)$ 这个 reward function 不需要是 differentiable我们也可以解接下来的问题。举例来说如果是在 GAN 里面,$R(\tau)$ 其实是一个 discriminator它就算是没有办法微分也无所谓你还是可以做接下来的运算。
还有另外一种critic这种critic 叫做 `Q-function`。它又叫做`state-action value function`
取 gradient之后我们背一个公式
$$
\nabla f(x)=f(x)\nabla \log f(x)
$$
我们可以对 $\nabla p_{\theta}(\tau)$ 使用这个公式,然后会得到 $\nabla p_{\theta}(\tau)=p_{\theta}(\tau) \nabla \log p_{\theta}(\tau)$。
* state value function 的 input 是一个 state它是根据 state 去计算出看到这个state 以后的 expected accumulated reward 是多少。
* state-action value function 的 input 是一个 state 跟 action 的 pair它的意思是说在某一个 state 采取某一个action假设我们都使用 actor $\pi$ ,得到的 accumulated reward 的期望值有多大。
接下来, 分子分母,上下同乘$p_{\theta}(\tau)$,然后我们可以得到下式:
$$
\frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)}=\log p_{\theta}(\tau)
$$
Q-function 有一个需要注意的问题是,这个 actor $\pi$,在看到 state s 的时候,它采取的 action 不一定是 a。Q-function 假设在 state s 强制采取 action a。不管你现在考虑的这个actor $\pi$ 它会不会采取action a这不重要。在state s 强制采取 action a。接下来都用 actor $\pi$ 继续玩下去,就只有在 state s我们才强制一定要采取action a接下来就进入自动模式让actor $\pi$ 继续玩下去,得到的 expected reward 才是$Q^{\pi}(s,a)$
然后如下式所示, 对 $\tau$ 进行求和,把 $R(\tau)$ 和 $\log p_{\theta}(\tau)$ 这两项 weighted by $ p_{\theta}(\tau)$ 既然有 weighted by $p_{\theta}(\tau)$,它们就可以被写成这个 expected 的形式。也就是你从 $p_{\theta}(\tau)$ 这个 distribution 里面 sample $\tau$ 出来, 去计算 $R(\tau)$ 乘上 $\nabla\log p_{\theta}(\tau)$,然后把它对所有可能的 $\tau$ 进行求和,就是这个 expected value
Q-function 有两种写法:
$$
\begin{aligned}
\nabla \bar{R}_{\theta}&=\sum_{\tau} R(\tau) \nabla p_{\theta}(\tau)\\&=\sum_{\tau} R(\tau) p_{\theta}(\tau) \frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)} \\&=
\sum_{\tau} R(\tau) p_{\theta}(\tau) \nabla \log p_{\theta}(\tau) \\
&=E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right]
\end{aligned}
$$
* input 是 state 跟actionoutput 就是一个 scalar
* input 是一个 state soutput 就是好几个 value。
实际上这个 expected value 没有办法算,所以你是用 sample 的方式来 sample 一大堆的 $\tau$。你 sample $N$ 笔 $\tau$ 然后你去计算每一笔的这些 value然后把它全部加起来最后你就得到你的 gradient。你就可以去 update 你的参数,你就可以去 update 你的 agent如下式所示。
$$
\begin{aligned}
E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\right] &\approx \frac{1}{N} \sum_{n=1}^{N} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(\tau^{n}\right) \\
&=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)
\end{aligned}
$$
注意 $p_{\theta}(\tau)$ 里面有两项,$p(s_{t+1}|s_t,a_t)$ 来自于 environment$p_\theta(a_t|s_t)$ 是来自于 agent。 $p(s_{t+1}|s_t,a_t)$ 由环境决定从而与 $\theta$ 无关,因此 $\nabla \log p(s_{t+1}|s_t,a_t) =0 $。因此 $\nabla p_{\theta}(\tau)=
\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$。
你可以非常直观的来理解这个部分,也就是在你 sample 到的 data 里面, 你 sample 到,在某一个 state $s_t$ 要执行某一个 action $a_t$ 这个 $s_t$ 跟 $a_t$ 它是在整个 trajectory $\tau$ 的里面的某一个 state and action 的 pair。
* 假设你在 $s_t$ 执行 $a_t$,最后发现 $\tau$ 的 reward 是正的, 那你就要增加这一项的概率,你就要增加在 $s_t$ 执行 $a_t$ 的概率。
* 反之,在 $s_t$ 执行 $a_t$ 会导致$\tau$ 的 reward 变成负的, 你就要减少这一项的概率。
假设 action 是 discrete 的action 就只有3 个可能,往左往右或是开火。那这个 Q-function output 的3 个 values 就分别代表 a 是向左的时候的 Q valuea 是向右的时候的Q value还有 a 是开火的时候的 Q value。
那你要注意的事情是,上图右边的 function 只有discrete action 才能够使用。如果 action 是无法穷举的,你只能够用上图左边这个式子,不能够用右边这个式子。
![](img/3.8.png)
这个怎么实现呢? 你用 gradient ascent 来 update 你的参数,你原来有一个参数 $\theta$ ,把你的 $\theta$ 加上你的 gradient 这一项,那当然前面要有个 learning ratelearning rate 其实也是要调的,你可用 Adam、RMSProp 等方法对其进行调整。
上图是文献上的结果,你去 estimate Q-function 的话,看到的结果可能会像是这个样子。这是什么意思呢?它说假设我们有 3 个 actions3 个 actions 就是原地不动、向上、向下。
我们可以套下面这个公式来把 gradient 计算出来:
* 假设是在第一个state不管是采取哪个action最后到游戏结束的时候得到的 expected reward 其实都差不多。因为球在这个地方就算是你向下接下来你其实应该还来的急救所以今天不管是采取哪一个action就差不了太多。
$$
\nabla \bar{R}_{\theta}=\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)
$$
实际上,要套上面这个公式, 首先你要先收集一大堆的 s 跟 a 的 pair你还要知道这些 s 跟 a 在跟环境互动的时候,你会得到多少的 reward。 这些资料怎么收集呢?你要拿你的 agent它的参数是 $\theta$,去跟环境做互动, 也就是拿你已经 train 好的 agent 先去跟环境玩一下,先去跟那个游戏互动一下, 互动完以后,你就会得到一大堆游戏的纪录,你会记录说,今天先玩了第一场,在第一场游戏里面,我们在 state $s_1$ 采取 action $a_1$,在 state $s_2$ 采取 action $a_2$ 。
* 假设在第二个state这个乒乓球它已经反弹到很接近边缘的地方这个时候你采取向上你才能得到positive 的reward才接的到球。如果你是站在原地不动或向下的话接下来你都会miss 掉这个球。你得到的reward 就会是负的
玩游戏的时候是有随机性的,所以 agent 本身是有随机性的,在同样 state $s_1$,不是每次都会采取 $a_1$,所以你要记录下来。在 state $s_1^1$ 采取 $a_1^1$,在 state $s_2^1$ 采取 $a_2^1$。整场游戏结束以后,得到的分数是$R(\tau^1)$。你会 sample 到另外一笔 data也就是另外一场游戏。在另外一场游戏里面你在 state $s_1^2$ 采取 $a_1^2$,在 state $s_2^2$ 采取 $a_2^2$,然后你 sample 到的就是 $\tau^2$得到的 reward 是 $R(\tau^2)$
* 假设在第三个state球很近了所以就要向上
你就可以把 sample 到的东西代到这个 gradient 的式子里面,把 gradient 算出来。也就是把这边的每一个 s 跟 a 的 pair 拿进来,算一下它的 log probability 。你计算一下在某一个 state 采取某一个 action 的 log probability然后对它取 gradient然后这个 gradient 前面会乘一个 weightweight 就是这场游戏的 reward。 有了这些以后,你就会去 update 你的 model
Update 完你的 model 以后。你要重新去收集 data再 update model。这边要注意一下一般 policy gradient sample 的 data 就只会用一次。你把这些 data sample 起来,然后拿去 update 参数,这些 data 就丢掉了。接着再重新 sample data才能够去 update 参数, 等一下我们会解决这个问题。
* 假设在第四个state球被反弹回去这时候采取那个action就都没有差了。
这个是 state-action value 的一个例子。
![](img/3.9.png)
虽然表面上我们 learn 一个 Q-function它只能拿来评估某一个 actor $\pi$ 的好坏,但只要有了这个 Q-function我们就可以做 reinforcement learning。有了这个 Q-function我们就可以决定要采取哪一个 action我们就可以进行`策略改进(Policy Improvement)`
接下来讲一些实现细节。实现方法是这个样子,把它想成一个分类的问题,在 classification 里面就是 input 一个 image然后 output 决定说是 10 个 class 里面的哪一个。在做 classification,我们要收集一堆 training data要有 input 跟 output 的 pair
在实现的时候,你就把 state 当作是 classifier 的 input。 你就当在做 image classification 的 problem只是现在的 class 不是说 image 里面有什么 objects。 现在的 class 是说,看到这张 image 我们要采取什么样的行为,每一个行为就是一个 class。比如说第一个 class 叫做向左,第二个 class 叫做向右,第三个 class 叫做开火。
这些训练的数据从哪里来的呢? 做分类的问题时,要有 input 和正确的 output。 这些训练数据是从 sampling 的 process 来的。假设在 sampling 的 process 里面,在某一个 state你 sample 到你要采取 action a 你就把这个 action a 当作是你的 ground truth。你在这个 state你 sample 到要向左。 本来向左这件事概率不一定是最高, 因为你是 sample它不一定概率最高。假设你 sample 到向左,在 training 的时候 你叫告诉 machine 说,调整 network 的参数, 如果看到这个 state你就向左。在一般的 classification 的 problem 里面,其实你在 implement classification 的时候, 你的 objective function 都会写成 minimize cross entropy其实 minimize cross entropy 就是 maximize log likelihood。
它的大原则是这样,假设你有一个初始的 actor也许一开始很烂 随机的也没有关系。初始的 actor 叫做 $\pi$,这个 $\pi$ 跟环境互动,会 collect data。接下来你 learn 一个 $\pi$ 这个 actor 的 Q value你去衡量一下 $\pi$ 这个actor 在某一个 state 强制采取某一个 action接下来用 $\pi$ 这个 policy 会得到的 expected reward那用 TD 或 MC 也是可以的。你 learn 出一个 Q-function 以后,就保证你可以找到一个新的 policy $\pi'$ policy $\pi'$ 一定会比原来的 policy $\pi$ 还要好。那等一下会定义说,什么叫做好。所以这边神奇的地方是,假设你有一个 Q-function 和 某一个policy $\pi$,你根据 policy $\pi$ learn 出 policy $\pi$ 的 Q-function接下来保证你可以找到一个新的 policy $\pi'$ ,它一定会比 $\pi$ 还要好,然后你用 $\pi'$ 取代 $\pi$,再去找它的 Q-function得到新的以后再去找一个更好的 policy。 然后这个循环一直下去,你的 policy 就会越来越好。
![](img/3.10.png)
上图就是讲我们刚才讲的到底是什么。
* 首先要定义的是什么叫做比较好?我们说$\pi'$ 一定会比$\pi$ 还要好什么叫做好呢这边所谓好的意思是说对所有可能的state s 而言对同一个state s 而言,$\pi$ 的 value function 一定会小于$\pi'$ 的value function。也就是说我们走到同一个 state s 的时候,如果拿 $\pi$ 继续跟环境互动下去,我们得到的 reward 一定会小于用$\pi'$ 跟环境互动下去得到的reward。所以不管在哪一个state你用$\pi'$ 去做interaction得到的expected reward 一定会比较大。所以 $\pi'$ 是比 $\pi$ 还要好的一个policy。
* 有了这个 Q-function 以后,怎么找这个 $\pi'$ 呢?事实上这个 $\pi'$ 是什么?这个$\pi'$ 就是, 如果你根据以下的这个式子去决定你的action
做 classification 的时候objective function 就是 maximize 或 minimize 的对象, 因为我们现在是 maximize likelihood 所以其实是 maximize 你要 maximize 的对象,如下式所示:
$$
\pi^{\prime}(s)=\arg \max _{a} Q^{\pi}(s, a)
\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)
$$
根据上式去决定你的action 的步骤叫做 $\pi'$ 的话,那这个 $\pi'$ 一定会比$\pi$ 还要好。这个意思是说,假设你已经 learn 出 $\pi$ 的Q-function今天在某一个 state s你把所有可能的 action a 都一一带入这个 Q-function看看说那一个 a 可以让 Q-function 的 value 最大,那这一个 action就是 $\pi'$ 会采取的 action。这边要注意一下给定这个 state s你的 policy $\pi$ 并不一定会采取 action a。我们是 给定某一个 state s 强制采取 action a用 $\pi$ 继续互动下去得到的 expected reward这个才是 Q-function 的定义。所以在 state s 里面不一定会采取 action a。假设用这一个 $\pi'$ 在 state s 采取action a 跟 $\pi$ 所谓采取 action 是不一定会一样的。然后 $\pi'$ 所采取的 action 会让他得到比较大的 reward
像这种 loss function。你可在 TensorFlow 里 call 现成的 function它就会自动帮你算
然后你就可以把 gradient 计算出来这是一般的分类问题。RL 唯一不同的地方是 loss 前面乘上一个 weight这个是整场游戏的时候得到的 total reward R 它并不是在 state s 采取 action a 的时候得到的 reward。 你要把你的每一笔 training data都 weighted by 这个 R。然后你用 TensorFlow 或 PyTorch 去帮你算 gradient 就结束了,跟一般 classification 差不多。
* 所以根本就没有一个 policy 叫做 $\pi'$,这个$\pi'$ 是用 Q-function 推出来的。所以没有另外一个 network 决定 $\pi'$ 怎么interaction有 Q-function 就可以找出$\pi'$。
* 但是这边有另外一个问题就是,在这边要解一个 arg max 的 problem。所以 a 如果是continuous 的就会有问题如果是discrete 的a 只有3 个选项,一个一个带进去, 看谁的 Q 最大,没有问题。但如果是 continuous 要解 arg max problem你就会有问题但这个是之后才会解决的
## Tips
这边有一些在实现的时候,你也许用得上的 tip
### Tip 1: Add a Baseline
![](img/3.11.png)
上图想要跟大家讲的是说,为什么用 $Q^{\pi}(s,a)$ 这个 Q-function 所决定出来的 $\pi'$,一定会比 $\pi$ 还要好
假设有一个policy 叫做 $\pi'$,它是由 $Q^{\pi}$ 决定的。我们要证对所有的 state s 而言,$V^{\pi^{\prime}}(s) \geq V^{\pi}(s)$。怎么证呢?我们先把$V^{\pi^{\prime}}(s)$写出来:
$$
V^{\pi}(s)=Q^{\pi}(s, \pi(s))
$$
假设在 state s 这个地方,你 follow $\pi$ 这个actor它会采取的action也就是$\pi(s)$,那你算出来的$Q^{\pi}(s, \pi(s))$ 会等于$V^{\pi}(s)$。In general 而言,$Q^{\pi}(s, \pi(s))$ 不见得等于$V^{\pi}(s)$ ,因为 action 不见得是$\pi(s)$。但如果这个 action 是 $\pi(s)$ 的话,$Q^{\pi}(s, \pi(s))$ 是等于$V^{\pi}(s)$的。
$Q^{\pi}(s, \pi(s))$ 还满足如下的关系:
$$
Q^{\pi}(s, \pi(s)) \le \max _{a} Q^{\pi}(s, a)
$$
因为这边是所有action 里面可以让 Q 最大的那个action所以今天这一项一定会比它大。那我们知道说这一项是什么这一项就是$Q^{\pi}(s, a)$$a$ 就是 $\pi'(s)$。因为$\pi'(s)$ output 的 a 就是可以让$Q^\pi(s,a)$ 最大的那一个。所以我们得到了下面的式子:
$$
\max _{a} Q^{\pi}(s, a)=Q^{\pi}\left(s, \pi^{\prime}(s)\right)
$$
于是:
$$
V^{\pi}(s) \leq Q^{\pi}\left(s, \pi^{\prime}(s)\right)
$$
也就是说某一个 state如果你按照policy $\pi$,一直做下去,你得到的 reward 一定会小于等于,在这个 state s。你故意不按照 $\pi$ 所给你指示的方向,而是按照 $\pi'$ 的方向走一步,但之后只有第一步是按照 $\pi'$ 的方向走只有在state s 这个地方,你才按照 $\pi'$ 的指示走,但接下来你就按照 $\pi$ 的指示走。虽然只有一步之差, 但是我从上面这个式子知道说,只有一步之差,你得到的 reward 一定会比完全 follow $\pi$ 得到的 reward 还要大。
那接下来你想要证的东西就是:
$$
Q^{\pi}\left(s, \pi^{\prime}(s) \right) \le V^{\pi'}(s)
$$
也就是说只有一步之差你会得到比较大的reward。但假设每步都是不一样的 每步都是 follow $\pi'$ 而不是$\pi$ 的话那你得到的reward 一定会更大。如果你要用数学式把它写出来的话,你可以这样写
$Q^{\pi}\left(s, \pi^{\prime}(s)\right)$这个式子它的意思就是说我们在state $s_t$ 采取 action $a_t$,得到 reward $r_{t+1}$然后跳到state $s_{t+1}$,即如下式所示:
$$
Q^{\pi}\left(s, \pi^{\prime}(s)\right)=E\left[r_{t+1}+V^{\pi}\left(s_{t+1}\right) \mid s_{t}=s, a_{t}=\pi^{\prime}\left(s_{t}\right)\right]
$$
这边有一个地方写得不太好,这边应该写成$r_t$ 跟之前的notation 比较一致,但这边写成了$r_{t+1}$,其实这都是可以的。在文献上有时候有人会说 在state $s_t$ 采取action $a_t$ 得到reward $r_{t+1}$ 有人会写成$r_t$但意思其实都是一样的。在state s按照$\pi'$ 采取某一个action $a_t$ 得到reward $r_{t+1}$然后跳到state $s_{t+1}$$V^{\pi}\left(s_{t+1}\right)$是state $s_{t+1}$,根据$\pi$ 这个actor 所估出来的value。这边要取一个期望值因为在同样的state 采取同样的action你得到的reward还有会跳到的 state 不一定是一样, 所以这边需要取一个期望值。
接下来我们会得到如下的式子:
$$
\begin{array}{l}
E\left[r_{t+1}+V^{\pi}\left(s_{t+1}\right) | s_{t}=s, a_{t}=\pi^{\prime}\left(s_{t}\right)\right] \\
\leq E\left[r_{t+1}+Q^{\pi}\left(s_{t+1}, \pi^{\prime}\left(s_{t+1}\right)\right) | s_{t}=s, a_{t}=\pi^{\prime}\left(s_{t}\right)\right]
\end{array}
$$
上式为什么成立呢?因为
$$
V^{\pi}(s) \leq Q^{\pi}\left(s, \pi^{\prime}(s)\right)
$$
也就是
$$
V^{\pi}(s_{t+1}) \leq Q^{\pi}\left(s_{t+1}, \pi^{\prime}(s_{t+1})\right)
$$
也就是说现在你一直follow $\pi$跟某一步follow $\pi'$接下来都follow $\pi$ 比起来某一步follow $\pi'$ 得到的reward 是比较大的。
接着我们得到下式:
$$
\begin{array}{l}
E\left[r_{t+1}+Q^{\pi}\left(s_{t+1}, \pi^{\prime}\left(s_{t+1}\right)\right) | s_{t}=s, a_{t}=\pi^{\prime}\left(s_{t}\right)\right] \\
=E\left[r_{t+1}+r_{t+2}+V^{\pi}\left(s_{t+2}\right) | \ldots\right]
\end{array}
$$
因为
$$
Q^{\pi}\left(s_{t+1}, \pi^{\prime}\left(s_{t+1}\right)\right) = r_{t+2}+V^{\pi}\left(s_{t+2}\right)
$$
然后你再代入
$$
V^{\pi}(s) \leq Q^{\pi}\left(s, \pi^{\prime}(s)\right)
$$
一直算到底算到episode 结束。那你就知道说
$$
V^{\pi}(s)\le V^{\pi'}(s)
$$
**从这边我们可以知道,你可以 estimate 某一个 policy 的 Q-function接下来你就可以找到另外一个 policy $\pi'$ 比原来的 policy 还要更好。**
## Target Network
第一个 tip 是 add 一个 baseline。add baseline 是什么意思呢?如果 given state s 采取 action a 会给你整场游戏正面的 reward就要增加它的概率。如果 state s 执行 action a整场游戏得到负的 reward就要减少这一项的概率
但在很多游戏里面, reward 总是正的,就是说最低都是 0。比如说打乒乓球游戏 你的分数就是介于 0 到 21 分之间,所以这个 R 总是正的。假设你直接套用这个式子, 在 training 的时候,告诉 model 说,不管是什么 action 你都应该要把它的概率提升。 在理想上,这么做并不一定会有问题。因为虽然说 R 总是正的,但它正的量总是有大有小,你在玩乒乓球那个游戏里面,得到的 reward 总是正的,但它是介于 0~21分之间有时候你采取某些 action 可能是得到 0 分,采取某些 action 可能是得到 20 分。
![](img/3.12.png)
接下来讲一下在 Q-learning 里你一定会用到的 tip。第一个是 `target network`,什么意思呢?我们在 learn Q-function 的时候,也会用到 TD 的概念。那怎么用 TD你现在收集到一个 data 是说在state $s_t$你采取action $a_t$ 以后你得到reward $r_t$ 然后跳到state $s_{t+1}$。然后根据这个Q-function你会知道说
假设你有 3 个 action a/b/c 可以执行,在某一个 state 有 3 个 action a/b/c可以执行。根据这个式子你要把这 3 项的概率, log probability 都拉高。 但是它们前面 weight 的这个 R 是不一样的。 R 是有大有小的weight 小的它上升的就少weight 多的,它上升的就大一点。 因为这个 log probability它是一个概率所以action a、b、c 的和要是 0。 所以上升少的,在做完 normalize 以后, 它其实就是下降的,上升的多的,才会上升。
![1](img/3.13.png)
这个是一个理想上的状况,但是实际上,我们是在做 sampling 就本来这边应该是一个 expectation summation over 所有可能的 s 跟 a 的 pair。 但你真正在学的时候,当然不可能是这么做的,你只是 sample 了少量的 s 跟 a 的 pair 而已。 因为我们做的是 sampling有一些 action 可能从来都没有 sample 到。在某一个 state1虽然可以执行的 action 有 a/b/c 3 个,但你可能只 sample 到 action b你可能只 sample 到 action c你没有 sample 到 action a。但现在所有 action 的 reward 都是正的,所以根据这个式子,它的每一项的概率都应该要上升。你会遇到的问题是,因为 a 没有被 sample 到,其它 action 的概率如果都要上升a 的概率就下降。 所以 a 不一定是一个不好的 action 它只是没被 sample 到。但只是因为它没被 sample 到, 它的概率就会下降,这个显然是有问题的,要怎么解决这个问题呢?你会希望你的 reward 不要总是正的。
![1.](img/3.14.png)
为了解决 reward 总是正的这个问题,你可以把 reward 减掉一项叫做 b这项 b 叫做 baseline。你减掉这项 b 以后,就可以让 $R(\tau^n)-b$ 这一项, 有正有负。 所以如果得到的 total reward $R(\tau^n)$ 大于 b 的话,就让它的概率上升。如果这个 total reward 小于 b就算它是正的正的很小也是不好的你就要让这一项的概率下降。 如果$R(\tau^n)<b$ 你就要让这个 state 采取这个 action 的分数下降 。这个 b 怎么设呢?一个最简单的做法就是, 你把 $\tau^n$ 的值取 expectation 算一下 $\tau^n$的平均值。
$$
\mathrm{Q}^{\pi}\left(s_{t}, a_{t}\right)
=r_{t}+\mathrm{Q}^{\pi}\left(s_{t+1}, \pi\left(s_{t+1}\right)\right)
b \approx E[R(\tau)]
$$
所以你在 learn 的时候,你会说我们有 Q-functioninput $s_t$, $a_t$ 得到的 value跟 input $s_{t+1}$, $\pi (s_{t+1})$ 得到的 value 中间,我们希望它差了一个$r_t$ 这跟刚才讲的TD 的概念是一样的
这是其中一种做法, 你可以想想看有没有其它的做法
但是实际上在 learn 的时候你会发现这样的一个function 并不好 learn因为假设这是一个 regression problem$\mathrm{Q}^{\pi}\left(s_{t}, a_{t}\right) $ 是 network 的 output$r_{t}+\mathrm{Q}^{\pi}\left(s_{t+1}, \pi\left(s_{t+1}\right)\right)$是 target你会发现 target 是会动的。当然你要 implement 这样的 training,其实也没有问题,就是你在做 backpropagation 的时候, $Q^{\pi}$ 的参数会被 update你会把两个 update 的结果加在一起。因为它们是同一个 model $Q^{\pi}$ 所以两个 update 的结果会加在一起。但这样会导致 training 变得不太稳定。因为假设你把 $\mathrm{Q}^{\pi}\left(s_{t}, a_{t}\right) $ 当作你model 的output $r_{t}+\mathrm{Q}^{\pi}\left(s_{t+1}, \pi\left(s_{t+1}\right)\right)$ 当作 target 的话。你要去 fit 的 target 是一直在变的,这种一直在变的 target 的 training 是不太好 train 的。所以你会把其中一个 Q-network通常是你会把右边这个 Q-network 固定住。也就是说你在 training 的时候,你只 update 左边这个 Q-network 的参数,而右边这个 Q-network 的参数会被固定住。因为右边的 Q-network 负责产生 target所以叫做 `target network`。因为 target network 是固定的,所以你现在得到的 target $r_{t}+\mathrm{Q}^{\pi}\left(s_{t+1}, \pi\left(s_{t+1}\right)\right)$ 的值也是固定的。因为 target network 是固定的,我们只调左边 network 的参数,它就变成是一个 regression problem。我们希望 model 的 output 的值跟目标越接近越好,你会 minimize 它的 mean square error
在实现的时候,你会把左边的 Q-network update 好几次以后,再去用 update 过的 Q-network 替换这个 target network 。但它们两个不要一起动,它们两个一起动的话, 结果会很容易坏掉。一开始这两个 network 是一样的,然后在 train 的时候,你会把右边的 Q-network fix 住。你在做 gradient decent 的时候,只调左边这个 network 的参数那你可能update 100 次以后才把这个参数复制到右边的 network 去,把它盖过去。把它盖过去以后,你这个 target value 就变了。就好像说你本来在做一个 regression problem那你 train 后把这个 regression problem 的 loss 压下去以后,接下来你把这边的参数把它 copy 过去以后,你的 target 就变掉了,接下来就要重新再 train。
所以在 implement training 的时候,你会不断地把 $R(\tau)$ 的分数记录下来 然后你会不断地去计算 $R(\tau)$ 的平均值, 你会把这个平均值,当作你的 b 来用。 这样就可以让你在 training 的时候, $\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$ 乘上前面这一项, 是有正有负的,这个是第一个 tip
### Tip 2: Assign Suitable Credit
### Intuition
第二个 tip给每一个 action 合适的 credit。什么意思呢如果我们看今天下面这个式子的话
$$
\nabla \bar{R}_{\theta} \approx \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}}\left(R\left(\tau^{n}\right)-b\right) \nabla \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right)
$$
我们原来会做的事情是,在某一个 state假设你执行了某一个 action a它得到的 reward ,它前面乘上的这一项 $R(\tau^n)-b$。
![](img/3.13.png)
下面我们通过猫追老鼠的例子来直观地理解为什么要 fix target network。猫是 `Q estimation`,老鼠是 `Q target`。一开始的话,猫离老鼠很远,所以我们想让这个猫追上老鼠。
![](img/3.14.png)
因为 Q target 也是跟模型参数相关的所以每次优化后Q target 也会动。这就导致一个问题,猫和老鼠都在动。
只要在同一个 Episode 里面,在同一场游戏里面, 所有的 state 跟 a 的 pair它都会 weighted by 同样的 reward term这件事情显然是不公平的因为在同一场游戏里面 也许有些 action 是好的,有些 action 是不好的。 假设整场游戏的结果是好的, 并不代表这个游戏里面每一个行为都是对的。若是整场游戏结果不好, 但不代表游戏里面的所有行为都是错的。所以我们希望可以给每一个不同的 action 前面都乘上不同的 weight。每一个 action 的不同 weight 它反映了每一个 action 到底是好还是不好。
![](img/3.15.png)
然后它们就会在优化空间里面到处乱动,就会产生非常奇怪的优化轨迹,这就使得训练过程十分不稳定。所以我们可以固定 Q target让老鼠动得不是那么频繁可能让它每 5 步动一次,猫则是每一步都在动。如果老鼠每 5 次动一步的话,猫就有足够的时间来接近老鼠。然后它们之间的距离会随着优化过程越来越小,最后它们就可以拟合,拟合过后就可以得到一个最好的 Q-network。
举个例子, 假设这个游戏都很短,只有 3~4 个互动, 在 $s_a$ 执行 $a_1$ 得到 5 分。在 $s_b$ 执行 $a_2$ 得到 0 分。在 $s_c$ 执行 $a_3$ 得到 -2 分。 整场游戏下来,你得到 +3 分,那你得到 +3 分 代表在 state $s_b$ 执行 action $a_2$ 是好的吗?并不见得代表 state $s_b$ 执行 $a_2$ 是好的。因为这个正的分数,主要来自于在 state $s_a$ 执行了 $a_1$,跟在 state $s_b$ 执行 $a_2$ 是没有关系的,也许在 state $s_b$ 执行 $a_2$ 反而是不好的, 因为它导致你接下来会进入 state $s_c$,执行 $a_3$ 被扣分,所以整场游戏得到的结果是好的, 并不代表每一个行为都是对的。
## Exploration
![](img/3.16.png)
![](img/3.16.png)第二个 tip 是`Exploration`。当我们使用 Q-function 的时候policy 完全 depend on Q-function。给定某一个 state你就穷举所有的 a 看哪个 a 可以让 Q value 最大它就是采取的action。那其实这个跟 policy gradient 不一样,在做 policy gradient 的时候output 其实是 stochastic 的。我们 output 一个action 的distribution根据这个action 的distribution 去做sample 所以在policy gradient 里面你每次采取的action 是不一样的是有随机性的。那像这种Q-function 如果你采取的action 总是固定的,会有什么问题呢?你会遇到的问题就是这不是一个好的收集 data 的方式。因为假设我们今天真的要估某一个state你可以采取action $a_{1}$, $a_{2}$, $a_{3}$。你要估测在某一个state 采取某一个action 会得到的Q value你一定要在那一个 state 采取过那一个action才估得出它的value。如果你没有在那个state 采取过那个action你其实估不出那个value 的。当然如果是用deep 的network就你的Q-function 其实是一个network这种情形可能会没有那么严重。但是 in general 而言,假设 Q-function 是一个table没有看过的 state-action pair它就是估不出值来。Network 也是会有一样的问题就是, 只是没有那么严重。所以今天假设你在某一个stateaction $a_{1}$, $a_{2}$, $a_{3}$ 你都没有采取过,那你估出来的 $Q(s,a_{1})$, $Q(s,a_{2})$, $Q(s,a_{3})$ 的 value 可能都是一样的,就都是一个初始值,比如说 0
如果按照我们刚才的讲法,整场游戏得到的分数是 3 分,那到时候在 training 的时候, 每一个 state 跟 action 的 pair都会被乘上 +3。 在理想的状况下,这个问题,如果你 sample 够多就可以被解决。因为假设你 sample 够多,在 state $s_b$ 执行 $a_2$ 的这件事情,被 sample 到很多。就某一场游戏,在 state $s_b$ 执行 $a_2$,你会得到 +3 分。 但在另外一场游戏,在 state $s_b$ 执行 $a_2$,你却得到了 -7 分,为什么会得到 -7 分呢? 因为在 state $s_b$ 执行 $a_2$ 之前, 你在 state $s_a$ 执行 $a_2$ 得到 -5 分,-5 分这件事可能也不是在 $s_b$ 执行 $a_2$ 的错,这两件事情,可能是没有关系的,因为它先发生了,这件事才发生,所以它们是没有关系的。
$$
\begin{array}{l}
Q(s, a_1)=0 \\
Q(s, a_2)=0 \\
Q(s, a_3)=0
\end{array}
$$
但是假设你在state s你sample 过某一个action $a_{2}$ ,它得到的值是 positive 的 reward。那 $Q(s, a_2)$ 就会比其他的action 都要好。在采取action 的时候, 就看说谁的Q value 最大就采取谁所以之后你永远都只会sample 到$a_{2}$其他的action 就再也不会被做了,所以就会有问题。就好像说你进去一个餐厅吃饭,其实你都很难选。你今天点了某一个东西以后,假说点了某一样东西, 比如说椒麻鸡,你觉得还可以。接下来你每次去就都会点椒麻鸡,再也不会点别的东西了,那你就不知道说别的东西是不是会比椒麻鸡好吃,这个是一样的问题。
如果你没有好的 exploration 的话, 你在training 的时候就会遇到这种问题。举一个实际的例子, 假设你今天是用 Q-learning 来玩比如说`slither.io`。在玩`slither.io` 你会有一个蛇,然后它在环境里面就走来走去, 然后就吃到星星它就加分。假设这个游戏一开始它采取往上走然后就吃到那个星星它就得到分数它就知道说往上走是positive。接下来它就再也不会采取往上走以外的action 了所以接下来就会变成每次游戏一开始它就往上冲然后就死掉再也做不了别的事。所以今天需要有exploration 的机制,需要让 machine 知道说虽然根据之前sample 的结果,$a_2$ 好像是不错的,但你至少偶尔也试一下$a_{1}$ 跟$a_{3}$,搞不好他们更好也说不定。
有两个方法解这个问题,一个是`Epsilon Greedy`。Epsilon Greedy 的意思是说,我们有$1-\varepsilon$ 的机率,通常$\varepsilon$ 就设一个很小的值, $1-\varepsilon$ 可能是90%也就是90% 的机率完全按照Q-function 来决定action。但是你有10% 的机率是随机的。通常在实现上 $\varepsilon$ 会随着时间递减。也就是在最开始的时候。因为还不知道那个action 是比较好的,所以你会花比较大的力气在做 exploration。接下来随着training 的次数越来越多。已经比较确定说哪一个Q 是比较好的。你就会减少你的exploration你会把 $\varepsilon$ 的值变小主要根据Q-function 来决定你的action比较少做random这是Epsilon Greedy。
还有一个方法叫做 `Boltzmann Exploration`,这个方法就比较像是 policy gradient。在 policy gradient 里面我们说network 的output 是一个 expected action space 上面的一个的 probability distribution。再根据 probability distribution 去做sample。那其实你也可以根据 Q value 去定一个probability distribution你可以说假设某一个action 的Q value 越大代表它越好那我们采取这个action 的机率就越高。但是某一个action 的Q value 小不代表我们不能trytry 看它好不好用。所以我们有时候也要trytry 那些 Q value 比较差的 action怎么做呢因为Q value 是有正有负的。所以你要把它弄成一个概率你可能就先取exponential然后再做normalize。然后把 $exp(Q(s,a))$ 做normalize 的这个概率当作是你在决定action 的时候sample 的概率。在实现上Q 是一个network所以你有点难知道 在一开始的时候network 的output 到底会长怎么样子。但是你可以猜测说, 假设你一开始没有任何的training data你的参数是随机的那给定某一个state s不同的 a output 的值,可能就是差不多的。所以一开始$Q(s,a)$ 应该会倾向于是uniform。也就是在一开始的时候你这个probability distribution 算出来它可能是比较uniform 的。
## Experience Replay
在 state $s_b$ 执行 $a_2$ 可能造成的问题只有会在接下来 -2 分,而跟前面的 -5 分没有关系的。但是假设我们今天 sample 到这项的次数够多,把所有发生这件事情的情况的分数通通都集合起来, 那可能不是一个问题。但现在的问题就是,我们 sample 的次数是不够多的。在 sample 的次数不够多的情况下,你要给每一个 state 跟 action pair 合理的 credit你要让大家知道它合理的 contribution。怎么给它一个合理的 contribution 呢? 一个做法是计算这个 pair 的 reward 的时候,不把整场游戏得到的 reward 全部加起来,**只计算从这一个 action 执行以后所得到的 reward**。因为这场游戏在执行这个 action 之前发生的事情是跟执行这个 action 是没有关系的, 所以在执行这个 action 之前得到多少 reward 都不能算是这个 action 的功劳。跟这个 action 有关的东西, 只有在执行这个 action 以后发生的所有的 reward 把它加起来,才是这个 action 真正的 contribution。所以在这个例子里面在 state $s_b$ 执行 $a_2$ 这件事情,也许它真正会导致你得到的分数应该是 -2 分而不是 +3 分,因为前面的 +5 分 并不是执行 $a_2$ 的功劳。实际上执行 $a_2$ 以后,到游戏结束前, 你只有被扣 2 分而已,所以它应该是 -2。那一样的道理今天执行 $a_2$ 实际上不应该是扣 7 分,因为前面扣 5 分,跟在 $s_b$ 这个 state 执行 $a_2$ 是没有关系的。在 $s_b$ 这个 state 执行 $a_2$,只会让你被扣两分而已,所以也许在 $s_b$ 这个 state 执行 $a_2$ 你真正会导致的结果只有扣两分而已。如果要把它写成式子的话是什么样子呢?如下式所示。
![](img/3.17.png)
第三个tip是`Experience Replay(经验回放)`。 Experience Replay 会构建一个 `Replay Buffer`Replay Buffer 又被称为 `Replay Memory`。Replay Buffer 是说现在会有某一个 policy $\pi$ 去跟环境做互动,然后它会去收集 data。我们会把所有的 data 放到一个buffer 里面buffer 里面就存了很多data。比如说 buffer 是 5 万,这样它里面可以存 5 万笔资料,每一笔资料就是记得说,我们之前在某一个 state $s_t$采取某一个action $a_t$,得到了 reward $r_t$。然后跳到 state $s_{t+1}$。那你用 $\pi$ 去跟环境互动很多次,把收集到的资料都放到这个 replay buffer 里面。
这边要注意是 replay buffer 里面的 experience 可能是来自于不同的 policy你每次拿 $\pi$ 去跟环境互动的时候,你可能只互动 10000 次,然后接下来你就更新你的 $\pi$ 了。但是这个 buffer 里面可以放 5 万笔资料,所以 5 万笔资料可能是来自于不同的 policy。Buffer 只有在它装满的时候,才会把旧的资料丢掉。所以这个 buffer 里面它其实装了很多不同的 policy 的 experiences。
本来的 weight 是整场游戏的 reward 的总和。那现在改成从某个时间 $t$ 开始,假设这个 action 是在 t 这个时间点所执行的,从 $t$ 这个时间点,一直到游戏结束所有 reward 的总和,才真的代表这个 action 是好的还是不好的。
![](img/3.18.png)
**接下来再更进一步,我们把未来的 reward 做一个 discount**,由此得到的回报被称为 `Discounted Return(折扣回报)`。为什么要把未来的 reward 做一个 discount 呢?因为虽然在某一个时间点,执行某一个 action会影响接下来所有的结果有可能在某一个时间点执行的 action接下来得到的 reward 都是这个 action 的功劳。但在比较真实的情况下, 如果时间拖得越长,影响力就越小。 比如说在第二个时间点执行某一个 action 那我在第三个时间点得到的 reward 可能是在第二个时间点执行某个 action 的功劳,但是在 100 个 timestamp 之后,又得到 reward那可能就不是在第二个时间点执行某一个 action 得到的功劳。 所以我们实际上在做的时候,你会在 R 前面乘上一个 `discount factor` $\gamma$ $\gamma \in [0,1] $ ,一般会设个 0.9 或 0.99
有了这个 buffer 以后,你是怎么 train 这个 Q 的 model 呢,怎么估 Q-function你的做法是这样你会 iterative 去 train 这个 Q-function在每一个 iteration 里面,你从这个 buffer 里面,随机挑一个 batch 出来,就跟一般的 network training 一样,你从那个 training data set 里面,去挑一个 batch 出来。你去 sample 一个 batch 出来,里面有一把的 experiences根据这把 experiences 去 update 你的 Q-function。就跟 TD learning 要有一个 target network 是一样的。你去 sample 一堆 batchsample 一个 batch 的 datasample 一堆 experiences然后再去 update 你的 Q-function。
* $\gamma = 0$ : Only care about the immediate reward
* $\gamma = 1$ : Future reward is equal to the immediate reward。
当我们这么做的时候, 它变成了一个 `off-policy` 的做法。因为本来我们的 Q 是要观察 $\pi$ 的 experience但实际上存在你的 replay buffer 里面的这些 experiences 不是通通来自于 $\pi$,有些是过去其他的 $\pi$ 所遗留下来的 experience。因为你不会拿某一个 $\pi$ 就把整个 buffer 装满,然后拿去测 Q-function这个 $\pi$ 只是 sample 一些 data 塞到那个 buffer 里面去,然后接下来就让 Q 去 train。所以 Q 在 sample 的时候, 它会 sample 到过去的一些资料
如果 time stamp $t'$ 越大,它前面就乘上越多次的 $\gamma$,就代表说现在在某一个 state $s_t$ 执行某一个 action $a_t$ 的时候,它真正的 credit 是在执行这个 action 之后所有 reward 的总和,而且你还要乘上 $\gamma$
但是这样做有什么好处呢?这么做有两个好处
举一个例子, 你就想成说,这是游戏的第 1、2、3、4 回合,那你在游戏的第二回合的某一个 $s_t$ 你执行 $a_t$,它真正的 credit 得到的分数应该是,假设你这边得到 +1 分 这边得到 +3 分,这边得到 -5 分,它的真正的 credit应该是 1 加上一个 discount 的 credit 叫做 $\gamma$ 乘上 3再加上 $\gamma^2$ 乘上 -5
* 第一个好处,其实在做 reinforcement learning 的时候, 往往最花时间的 step 是在跟环境做互动train network 反而是比较快的。因为你用 GPU train 其实很快, 真正花时间的往往是在跟环境做互动。用 replay buffer 可以减少跟环境做互动的次数,因为在做 training 的时候你的experience 不需要通通来自于某一个policy。一些过去的 policy 所得到的 experience 可以放在 buffer 里面被使用很多次,被反复的再利用,这样让你的 sample 到 experience 的利用是比较 efficient。
* 第二个好处,在 train network 的时候,其实我们希望一个 batch 里面的 data 越 diverse 越好。如果你的 batch 里面的 data 都是同样性质的,你 train 下去是容易坏掉的。如果 batch 里面都是一样的data你 train 的时候performance 会比较差。我们希望 batch data 越 diverse 越好。那如果你今天你的这个buffer 里面的那些experience 通通来自于不同的policy 那你sample 到的一个batch 里面的data 会是比较diverse 。
Q我们明明是要观察 $\pi$ 的 value里面混杂了一些不是 $\pi$ 的 experience ,这有没有关系?
A没关系。这并不是因为过去的 $\pi$ 跟现在的 $\pi$ 很像, 就算过去的$\pi$ 没有很像,其实也是没有关系的。主要的原因是因为, 我们并不是去sample 一个trajectory我们只sample 了一笔experience所以跟是不是 off-policy 这件事是没有关系的。就算是off-policy就算是这些 experience 不是来自于 $\pi$,我们其实还是可以拿这些 experience 来估测 $Q^{\pi}(s,a)$。这件事有点难解释,不过你就记得说 Experience Replay 在理论上也是没有问题的。
## DQN
如果大家可以接受这样子的话, 实际上就是这么 implement 的。这个 b 可以是 state-dependent 的,事实上 b 它通常是一个 network estimate 出来的,它是一个 network 的 output。
![](img/3.19.png)
把 $R-b$ 这一项合起来,我们统称为` advantage function``A` 来代表 advantage function。Advantage function 是 dependent on s and a我们就是要计算的是在某一个 state s 采取某一个 action a 的时候advantage function 有多大。
上图就是一般的 `Deep Q-network(DQN)` 的算法。
这个算法是这样的。Initialize 的时候,你 initialize 2 个network一个是 Q一个是 $\hat{Q}$,其实 $\hat{Q}$ 就等于 Q。一开始这个 target Q-network跟你原来的 Q-network 是一样的。在每一个 episode你拿你的 actor 去跟环境做互动,在每一次互动的过程中,你都会得到一个 state $s_t$那你会采取某一个action $a_t$。怎么知道采取哪一个action $a_t$ 呢?你就根据你现在的 Q-function。但是你要有 exploration 的机制。比如说你用 Boltzmann exploration 或是 Epsilon Greedy 的 exploration。那接下来你得到 reward $r_t$,然后跳到 state $s_{t+1}$。所以现在 collect 到一笔 data这笔 data 是 ($s_t$, $a_t$ ,$r_t$, $s_{t+1}$)。这笔 data 就塞到你的 buffer 里面去。如果 buffer 满的话, 你就再把一些旧的资料丢掉。接下来你就从你的buffer 里面去 sample data那你 sample 到的是 $(s_{i}, a_{i}, r_{i}, s_{i+1})$。这笔data 跟你刚放进去的不一定是同一笔,你可能抽到一个旧的。要注意的是,其实你 sample 出来不是一笔 data你 sample 出来的是一个 batch 的 data你 sample 一个batch 出来sample 一把 experiences 出来。接下来就是计算你的 target。假设你 sample 出这么一笔 data。根据这笔 data 去算你的 target。你的 target 是什么呢target 记得要用 target network $\hat{Q}$ 来算。Target 是:
$$
y=r_{i}+\max _{a} \hat{Q}\left(s_{i+1}, a\right)
$$
其中 a 就是让 $\hat{Q}$ 的值最大的 a。因为我们在 state $s_{i+1}$会采取的action a其实就是那个可以让 Q value 的值最大的那一个 a。接下来我们要update Q 的值,那就把它当作一个 regression problem。希望$Q(s_i,a_i)$ 跟你的target 越接近越好。然后假设已经 update 了某一个数量的次,比如说 C 次,设 C = 100 那你就把 $\hat{Q}$ 设成 Q这就是 DQN。最后我们给出 [DQN 的 PyTorch 实现](https://github.com/qfettes/DeepRL-Tutorials/blob/master/01.DQN.ipynb) 。
这个 advantage function 它的上标是 $\theta$ $\theta$ 是什么意思呢? 因为在算 advantage function时你要计算$\sum_{t^{\prime}=t}^{T_{n}} r_{t^{\prime}}^{n}$ ,你会需要有一个 interaction 的结果。你会需要有一个 model 去跟环境做 interaction你才知道你接下来得到的 reward 会有多少。这个 $\theta$ 就是代表说是用 $\theta$ 这个 model 跟环境去做 interaction然后你才计算出这一项。从时间 t 开始到游戏结束为止,所有 R 的 summation 把这一项减掉 b然后这个就叫 advantage function。它的意义就是假设我们在某一个 state $s_t$ 执行某一个 action $a_t$,相较于其他可能的 action它有多好。它真正在意的不是一个绝对的好 而是说在同样的 state 的时候 是采取某一个 action $a_t$ 相较于其它的 action 它有多好,它是相对的好。因为会减掉一个 b减掉一个 baseline 所以这个东西是相对的好,不是绝对的好。 $A^{\theta}\left(s_{t}, a_{t}\right)$ 通常可以是由一个 network estimate 出来的,这个 network 叫做 critic。
## References
* [Intro to Reinforcement Learning (强化学习纲要)](https://github.com/zhoubolei/introRL)
* [神经网络与深度学习](https://nndl.github.io/)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 376 KiB

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 922 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Some files were not shown because too many files have changed in this diff Show More