fix ch4 typos

This commit is contained in:
qiwang067
2020-08-31 22:01:09 +08:00
parent 316fa93cb1
commit 975dda0812

View File

@@ -35,7 +35,7 @@
![](img/4.3.png) ![](img/4.3.png)
接下来用一个例子来说明 actor 是怎么样跟环境互动的。 首先 actor 会看到一个游戏画面,我们用 $s_1$ 来表示这个游戏画面,它代表游戏初始的画面。接下来 actor 看到这个游戏的初始画面以后,根据它内部的 network根据它内部的 policy 来决定一个 action。假设它现在决定的 action 是向右,它决定完 action 以后,它就会得到一个 reward ,代表它采取这个 action 以后得到的分数。 接下来用一个例子来说明 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 决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。 我们把一开始的初始画面作 $s_1$ 把第一次执行的动作记作 $a_1$,把第一次执行动作完以后得到的 reward 记作 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$这个都可以你自己看得懂就好。Actor 决定一个的行为以后, 就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给 actor这个 actor 决定要开火,然后它可能杀了一只怪,就得到五分。这个 process 就反复地持续下去,直到今天走到某一个 timestamp 执行某一个 action得到 reward 之后, 这个 environment 决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。
![](img/4.4.png) ![](img/4.4.png)
一场游戏叫做一个 `Episode(回合)` 或者 `Trial(试验)`。把这个游戏里面,所有得到的 reward 都总合起来,就是 `Total reward`,我们称其为`Return(回报)`,用 R 来表示它。Actor 要想办法去 maximize 它可以得到的 reward。 一场游戏叫做一个 `Episode(回合)` 或者 `Trial(试验)`。把这个游戏里面,所有得到的 reward 都总合起来,就是 `Total reward`,我们称其为`Return(回报)`,用 R 来表示它。Actor 要想办法去 maximize 它可以得到的 reward。
@@ -58,7 +58,7 @@ p_{\theta}(\tau)
\end{aligned} \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$。 怎么算呢,如上式所示。在假设 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就是主机它内部设定是怎样。看今天这个主机在决定要输出什么样的游戏画面的时候有没有概率。因为如果没有概率的话这个游戏的每次的行为都一样你只要找到一条 path 就可以过关了,这样感觉是蛮无聊的 。所以游戏里面,通常是还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。Process 就反复继续下去,你就可以计算一个 trajectory $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。
@@ -231,7 +231,7 @@ $$
把 $R-b$ 这一项合起来,我们统称为` advantage function``A` 来代表 advantage function。Advantage function 是 dependent on s and a我们就是要计算的是在某一个 state s 采取某一个 action a 的时候advantage function 有多大。 把 $R-b$ 这一项合起来,我们统称为` advantage function``A` 来代表 advantage function。Advantage function 是 dependent on s and a我们就是要计算的是在某一个 state s 采取某一个 action a 的时候advantage function 有多大。
在算 advantage function 时,你要计算$\sum_{t^{\prime}=t}^{T_{n}} r_{t^{\prime}}^{n}$ ,你需要有一个互动的结果。你需要有一个 model 去跟环境做互动,你才知道接下来得到的 reward 会有多少。这个 advantage function 的上标是 $\theta$$\theta$ 就是代表说是用 $\theta$ 这个 model 跟环境去做互动,然后你才计算出这一项。从时间 t 开始到游戏结束为止,所有 r 的加和减掉 b这个就叫 advantage function。 在算 advantage function 时,你要计算 $\sum_{t^{\prime}=t}^{T_{n}} r_{t^{\prime}}^{n}$ ,你需要有一个互动的结果。你需要有一个 model 去跟环境做互动,你才知道接下来得到的 reward 会有多少。这个 advantage function 的上标是 $\theta$$\theta$ 就是代表说是用 $\theta$ 这个 model 跟环境去做互动,然后你才计算出这一项。从时间 t 开始到游戏结束为止,所有 r 的加和减掉 b这个就叫 advantage function。
Advantage function 的意义就是,假设我们在某一个 state $s_t$ 执行某一个 action $a_t$,相较于其他可能的 action它有多好。它在意的不是一个绝对的好而是相对的好`相对优势(relative advantage)`。因为会减掉一个 b减掉一个 baseline 所以这个东西是相对的好,不是绝对的好。 $A^{\theta}\left(s_{t}, a_{t}\right)$ 通常可以是由一个 network estimate 出来的,这个 network 叫做 critic。 Advantage function 的意义就是,假设我们在某一个 state $s_t$ 执行某一个 action $a_t$,相较于其他可能的 action它有多好。它在意的不是一个绝对的好而是相对的好`相对优势(relative advantage)`。因为会减掉一个 b减掉一个 baseline 所以这个东西是相对的好,不是绝对的好。 $A^{\theta}\left(s_{t}, a_{t}\right)$ 通常可以是由一个 network estimate 出来的,这个 network 叫做 critic。
@@ -239,9 +239,9 @@ Advantage function 的意义就是,假设我们在某一个 state $s_t$ 执行
![](img/4.20.png) ![](img/4.20.png)
蒙特卡洛可以理解为算法完成一个 episode 之后,再拿这个 episode 的数据来去 learn 一下,做一次更新。因为我们已经拿到了一整 episode 的数据的话,也能够拿到每一个 step 的那个 reward我们可以很方便去计算每个 step 的未来总收益,就是我们的期望,就是我们的回报 $G_t$ 。$G_t$是我们的未来总收益,$G_t$代表是从这个 step 后面我能拿到的收益之和是多少。$G_1$是说我从第一步开始,往后能够拿到多少的收益。$G_2$ 的话也是说从第二步这里开始,往后能够拿到一共拿到多少的收益。 蒙特卡洛可以理解为算法完成一个 episode 之后,再拿这个 episode 的数据来去 learn 一下,做一次更新。因为我们已经拿到了一整 episode 的数据的话,也能够拿到每一个 step 的 reward我们可以很方便去计算每个 step 的未来总收益,就是我们的期望,就是我们的回报 $G_t$ 。$G_t$ 是我们的未来总收益,$G_t$ 代表是从这个 step 后面我能拿到的收益之和是多少。$G_1$是说我从第一步开始,往后能够拿到多少的收益。$G_2$ 是说从第二步开始,往后一共能够拿到多少的收益。
相比蒙特卡洛还是一个 episode 更新一次这样子的方式,时序差分就是每个 step 都更新一下。每走一步,我就更新下,这样的更新频率会更高一点。它拿的是 Q-function 来去近似地表示我的未来总收益 $G_t$。 相比蒙特卡洛还是一个 episode 更新一次这样子的方式,时序差分就是每个 step 都更新一下。每走一步,我就更新下,这样的更新频率会更高一点。它拿的是 Q-function 来去近似地表示我的未来总收益 $G_t$。
举个例子来解释时序差分强化学习和蒙特卡洛强化学习的区别, 举个例子来解释时序差分强化学习和蒙特卡洛强化学习的区别,
@@ -253,13 +253,13 @@ Advantage function 的意义就是,假设我们在某一个 state $s_t$ 执行
* 时序差分强化学习会在路口 A 就开始更新预计到达路口 B、路口 C $\cdots \cdots$, 以及到达公司的时间; * 时序差分强化学习会在路口 A 就开始更新预计到达路口 B、路口 C $\cdots \cdots$, 以及到达公司的时间;
* 而蒙特卡洛强化学习并不会立即更新时间,而是在到达公司后,再修改到达每个路口和公司的时间。 * 而蒙特卡洛强化学习并不会立即更新时间,而是在到达公司后,再修改到达每个路口和公司的时间。
时序差分强化学习能够在知道结果之前就开始学习,相比蒙特卡洛强化学习,其更快速、灵活。 **时序差分强化学习能够在知道结果之前就开始学习,相比蒙特卡洛强化学习,其更快速、灵活。**
![](img/4.21.png) ![](img/4.21.png)
我们介绍下策略梯度最简单的也是最经典的一个算法 `REINFORCE`。REINFORCE 用的是回合更新的方式。它在代码上的处理上是先拿到每个 step 的 reward然后计算每个 step 的未来总收益 $G_t$ 是多少,然后拿每个 $G_t$ 代入公式,去优化每一个 action 的输出。所以编写代码时会有这样一个函数,输入每个 step 拿到的 reward然后把这些 reward 转成每一个 step 的未来总收益。因为未来总收益是这样计算的: 我们介绍下策略梯度最简单的也是最经典的一个算法 `REINFORCE`。REINFORCE 用的是回合更新的方式。它在代码上的处理上是先拿到每个 step 的 reward然后计算每个 step 的未来总收益 $G_t$ 是多少,然后拿每个 $G_t$ 代入公式,去优化每一个 action 的输出。所以编写代码时会有这样一个函数,输入每个 step 拿到的 reward把这些 reward 转成每一个 step 的未来总收益。因为未来总收益是这样计算的:
$$ $$
\begin{aligned} \begin{aligned}
G_{t} &=\sum_{k=t+1}^{T} \gamma^{k-t-1} r_{k} \\ G_{t} &=\sum_{k=t+1}^{T} \gamma^{k-t-1} r_{k} \\
@@ -270,27 +270,27 @@ $$
![](img/4.22.png) ![](img/4.22.png)
REINFORCE 代码主要看最后四行,先产生一个 episode 的数据,比如 $(s_1,a_1,G_1),(s_2,a_2,G_2),\cdots,(s_T,a_T,G_T)$。然后针对每个 action 来计算梯度。 在代码上计算时,我们要拿到神经网络的输出。神经网络会输出每个 action 对应的概率值,然后我们还可以拿到实际的 action把它转成 one-hot 向量乘一下,我们可以拿到 $\ln \pi(A_t|S_t,\theta)$ 。 REINFORCE 的伪代码主要看最后四行,先产生一个 episode 的数据,比如 $(s_1,a_1,G_1),(s_2,a_2,G_2),\cdots,(s_T,a_T,G_T)$。然后针对每个 action 来计算梯度。 在代码上计算时,我们要拿到神经网络的输出。神经网络会输出每个 action 对应的概率值,然后我们还可以拿到实际的 action把它转成 one-hot 向量乘一下,我们可以拿到 $\ln \pi(A_t|S_t,\theta)$ 。
![](img/4.23.png) ![](img/4.23.png)
手写数字识别是经典的一个多分类问题,就是输入一张手写数字的图片,经过神经网络输出的是各个分类的一个概率。目的是希望输出的这个概率的分布尽可能地去贴近真实值的概率分布。因为真实值只有一个数字 9可是你用这个 one-hot 向量的形式去给编码的话,也可以理解为这个真实值也是一个概率分布9 的概率就是1其他的概率就是 0。神经的网络输出一开始可能会比较平均通过不断迭代训练优化之后,我会希望 9 输出的概率可以远高于其他数字输出的概率。 手写数字识别是一个经典的多分类问题,就是输入一张手写数字的图片,经过神经网络输出的是各个分类的一个概率。目的是希望输出的这个概率的分布尽可能地去贴近真实值的概率分布。因为真实值只有一个数字 9你用这个 one-hot 向量的形式去给编码的话,也可以这个真实值理解为一个概率分布9 的概率就是1其他的概率就是 0。神经的网络输出一开始可能会比较平均通过不断迭代训练优化之后,我会希望 9 输出的概率可以远高于其他数字输出的概率。
![](img/4.24.png) ![](img/4.24.png)
如上图所示,就是提高 9 对应的概率,降低其他数字对应的概率让神经网络输出的概率能够更贴近这个真实值的概率分布。我们可以用交叉熵(Cross Entropy)来去表示两个概率分布之间的差距。 如上图所示,就是提高 9 对应的概率,降低其他数字对应的概率让神经网络输出的概率能够更贴近这个真实值的概率分布。我们可以用`交叉熵(Cross Entropy)`来去表示两个概率分布之间的差距。
![](img/4.25.png) ![](img/4.25.png)
我们看一下它的优化流程,就是怎么让这个输出去逼近这个真实值。它的优化流程就是将图片作为输入传给神经网络,然后神经网络会这个图片属于哪一类数字,输出所有数字可能的概率然后再计算这个交叉熵,就是神经网络的输出 $Y_i$ 和真实的标签值 $Y_i'$ 之间的距离 $-\sum Y_{i}^{\prime} \cdot \log \left(Y_{i}\right)$。我们希望尽可能地缩小这两个概率分布之间的差距,计算出来的 cross entropy 可以作为这个 loss 函数传给神经网络里面的优化器去优化,去自动去做神经网络的参数更新。 我们看一下它的优化流程,就是怎么让这个输出去逼近这个真实值。它的优化流程就是将图片作为输入传给神经网络,神经网络会判断这个图片属于哪一类数字,输出所有数字可能的概率然后再计算这个交叉熵,就是神经网络的输出 $Y_i$ 和真实的标签值 $Y_i'$ 之间的距离 $-\sum Y_{i}^{\prime} \cdot \log \left(Y_{i}\right)$。我们希望尽可能地缩小这两个概率分布之间的差距,计算出来的 cross entropy 可以作为这个 loss 函数传给神经网络里面的优化器去优化,去自动去做神经网络的参数更新。
![](img/4.26.png) ![](img/4.26.png)
类似policy gradient 预测每一个状态下面应该要输出的这个行动的概率,就是输入状态 $s_t$,然后输出动作的概率,比如 0.020.080.09。实际上输出给环境的动作是随机选了一个 action比如说我选了右这个 action它的 one-hot 向量就是 001。我们把神经网络的输出和实际动作带入 cross entropy 的公式就可以求出输出的概率和实际的动作之间的差距。但这个实际的动作 $a_t$ 只是我们输出的真实的 action它并不一定是正确的 action它不能像那个手写数字识别一样作为一个正确的标签来去指导我的神经网络朝着正确的方向去更新所以我们在这里会需要乘以一个奖励回报 $G_t$。这个奖励回报相当于是对这个真实 action 的评价,$G_t$ 具体越大,未来总收益越大,说明当前输出的这个真实的 action 就越好,这个 loss 就越需要重视。如果 $G_t$ 越小,那就说明做这个 action $a_t$ 并没有那么的好,那我的 loss 的权重就要小一点优化力度就小一点。通过这个和那个手写输入识别的一个对比,我们就知道为什么 loss 会构造成这个样子。 类似policy gradient 预测每一个状态下面应该要输出的这个行动的概率,就是输入状态 $s_t$,然后输出动作的概率,比如 0.020.080.09。实际上输出给环境的动作是随机选了一个 action比如说我选了右这个 action它的 one-hot 向量就是 001。我们把神经网络的输出和实际动作带入 cross entropy 的公式就可以求出输出的概率和实际的动作之间的差距。但这个实际的动作 $a_t$ 只是我们输出的真实的 action它并不一定是正确的 action它不能像手写数字识别一样作为一个正确的标签来去指导神经网络朝着正确的方向去更新所以我们在这里会需要乘以一个奖励回报 $G_t$。这个奖励回报相当于是对这个真实 action 的评价,$G_t$ 具体越大,未来总收益越大,说明当前输出的这个真实的 action 就越好,这个 loss 就越需要重视。如果 $G_t$ 越小,那就说明做这个 action $a_t$ 并没有那么的好loss 的权重就要小一点优化力度就小一点。通过这个和那个手写输入识别的一个对比,我们就知道为什么 loss 会构造成这个样子。
![](img/4.27.png) ![](img/4.27.png)
实际上我们在计算这个 loss 的时候,我们要拿到那个 $\ln \pi(A_t|S_t,\theta)$。我就拿我实际执行的这个动作,先取个 one-hot 向量,然后再拿到神经网络预测的动作概率,这两个一相乘,我就可以拿到算法里面的那个 $\ln \pi(A_t|S_t,\theta)$。这个就是我们要构造的 loss。因为我们会拿到整个 episode 的所有的轨迹,所以我们可以对这个这一条整条轨迹里面的每个 action 都去计算一个 loss。把所有的 loss 加起来之后,我们再扔给那个 adam 的优化器去自动更新参数就好了。 实际上我们在计算这个 loss 的时候,我们要拿到那个 $\ln \pi(A_t|S_t,\theta)$。我就拿我实际执行的这个动作,先取个 one-hot 向量,然后再拿到神经网络预测的动作概率,这两个一相乘,我就可以拿到算法里面的那个 $\ln \pi(A_t|S_t,\theta)$。这个就是我们要构造的 loss。因为我们会拿到整个 episode 的所有的轨迹,所以我们可以对这一条整条轨迹里面的每个 action 都去计算一个 loss。把所有的 loss 加起来之后,我们再扔给那个 adam 的优化器去自动更新参数就好了。
![](img/4.28.png) ![](img/4.28.png)