From 3f5d997c3f825b439b8ef880f0332be84d00b3c7 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Sat, 12 Dec 2020 11:32:48 +0800 Subject: [PATCH 01/13] fix ch4 typos --- docs/chapter4/chapter4.md | 177 +++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/docs/chapter4/chapter4.md b/docs/chapter4/chapter4.md index 46b0242..9636ae6 100644 --- a/docs/chapter4/chapter4.md +++ b/docs/chapter4/chapter4.md @@ -3,58 +3,58 @@ ![](img/4.1.png) -在 reinforcement learning 中有 3 个 components:`actor`、`environment` 和 `reward function`。 +在强化学习中有 3 个组成部分:`演员(actor)`、`环境(environment)` 和 `奖励函数(reward function)`。 -让机器玩 video game 时, +让机器玩视频游戏时, -* actor 做的事情就是去操控游戏的摇杆, 比如说向左、向右、开火等操作; -* environment 就是游戏的主机, 负责控制游戏的画面负责控制说,怪物要怎么移动, 你现在要看到什么画面等等; -* reward function 就是当你做什么事情,发生什么状况的时候,你可以得到多少分数, 比如说杀一只怪兽得到 20 分等等。 +* 演员做的事情就是去操控游戏的摇杆, 比如说向左、向右、开火等操作; +* 环境就是游戏的主机, 负责控制游戏的画面负责控制说,怪物要怎么移动, 你现在要看到什么画面等等; +* 奖励函数就是当你做什么事情,发生什么状况的时候,你可以得到多少分数, 比如说杀一只怪兽得到 20 分等等。 同样的概念用在围棋上也是一样的, -* actor 就是 alpha Go,它要决定下哪一个位置; -* environment 就是对手; -* reward function 就是按照围棋的规则, 赢就是得一分,输就是负一分等等。 +* 演员就是 alpha Go,它要决定下哪一个位置; +* 环境就是对手; +* 奖励函数就是按照围棋的规则, 赢就是得一分,输就是负一分等等。 -在 reinforcement learning 里面,environment 跟 reward function 不是你可以控制的,environment 跟 reward function 是在开始学习之前,就已经事先给定的。你唯一能做的事情是调整 actor 里面的 policy,使得 actor 可以得到最大的 reward。Actor 里面会有一个 policy, 这个 policy 决定了 actor 的行为。Policy 就是给一个外界的输入,然后它会输出 actor 现在应该要执行的行为。 +在强化学习里面,环境跟奖励函数不是你可以控制的,环境跟奖励函数是在开始学习之前,就已经事先给定的。你唯一能做的事情是调整 演员里面的策略(policy),使得 演员可以得到最大的奖励。演员里面会有一个策略, 这个策略决定了演员的行为。策略就是给一个外界的输入,然后它会输出演员现在应该要执行的行为。 ![](img/4.2.png) -* Policy 一般写成 $\pi$。假设你是用 deep learning 的技术来做 reinforcement learning 的话,**policy 就是一个 network**。Network 里面就有一堆参数, 我们用 $\theta$ 来代表 $\pi$ 的参数。 +* 策略一般写成 $\pi$。假设你是用深度学习的技术来做强化学习的话,**策略就是一个网络**。网络里面就有一堆参数, 我们用 $\theta$ 来代表 $\pi$ 的参数。 -* **Network 的 input 就是现在 machine 看到的东西**,如果让 machine 打电玩的话,machine 看到的东西就是游戏的画面。Machine 看到什么东西,会影响你现在 training 到底好不好 train。举例来说,在玩游戏的时候, 也许你觉得游戏的画面,前后是相关的,也许你觉得说,你应该让你的 policy,看从游戏初始到现在这个时间点,所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子会比较难处理。要让你的 machine,你的 policy 看到什么样的画面, 这个是你自己决定的。让你知道说给机器看到什么样的游戏画面,可能是比较有效的。 -* **Output 的就是机器要采取什么样的行为。** +* **网络的输入就是现在机器看到的东西**,如果让机器打电玩的话,机器看到的东西就是游戏的画面。机器看到什么东西,会影响你现在训练到底好不好训练。举例来说,在玩游戏的时候, 也许你觉得游戏的画面,前后是相关的,也许你觉得说,你应该让你的策略,看从游戏初始到现在这个时间点,所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子会比较难处理。要让你的机器,你的策略 看到什么样的画面, 这个是你自己决定的。让你知道说给机器看到什么样的游戏画面,可能是比较有效的。 +* **输出的就是机器要采取什么样的行为。** * 上图就是具体的例子, - * policy 就是一个 network; - * input 就是游戏的画面,它通常是由 pixels 所组成的; - * output 就是看看说有哪些选项是你可以去执行的,output layer 就有几个 neurons。 - * 假设你现在可以做的行为有 3 个,output layer 就是有 3 个 neurons。每个 neuron 对应到一个可以采取的行为。 - * Input 一个东西后,network 就会给每一个可以采取的行为一个分数。你可以把这个分数当作是概率。 actor 就是看这个概率的分布,根据这个概率的分布来决定它要采取的行为。比如说 70% 会走 left,20% 走 right,10% 开火等等。概率分布不同,actor 采取的行为就会不一样。 + * 策略就是一个网络; + * 输入 就是游戏的画面,它通常是由像素(pixels)所组成的; + * 输出就是看看说有哪些选项是你可以去执行的,输出层就有几个神经元。 + * 假设你现在可以做的行为有 3 个,输出层就是有 3 个神经元。每个神经元对应到一个可以采取的行为。 + * 输入一个东西后,网络就会给每一个可以采取的行为一个分数。你可以把这个分数当作是概率。演员就是看这个概率的分布,根据这个概率的分布来决定它要采取的行为。比如说 70% 会走 left,20% 走 right,10% 开火等等。概率分布不同,演员采取的行为就会不一样。 ![](img/4.3.png) -**接下来用一个例子来说明 actor 是怎么样跟环境互动的。** +**接下来用一个例子来说明演员是怎么样跟环境互动的。** -首先 actor 会看到一个游戏画面,我们用 $s_1$ 来表示游戏初始的画面。接下来 actor 看到这个游戏的初始画面以后,根据它内部的 network,根据它内部的 policy 来决定一个 action。假设它现在决定的 action 是向右,它决定完 action 以后,它就会得到一个 reward ,代表它采取这个 action 以后得到的分数。 +首先演员会看到一个游戏画面,我们用 $s_1$ 来表示游戏初始的画面。接下来演员看到这个游戏的初始画面以后,根据它内部的网络,根据它内部的策略来决定一个动作。假设它现在决定的动作 是向右,它决定完动作 以后,它就会得到一个奖励,代表它采取这个动作以后得到的分数。 -我们把一开始的初始画面记作 $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$,把第一次执行动作完以后得到的奖励记作 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$,这个都可以,你自己看得懂就好。演员 决定一个行为以后, 就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给演员,这个演员决定要开火,然后它可能杀了一只怪,就得到五分。这个过程就反复地持续下去,直到今天走到某一个时间点执行某一个动作,得到奖励之后, 这个环境决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。 ![](img/4.4.png) -* 一场游戏叫做一个 `episode(回合)` 或者 `trial(试验)`。 -* 把这场游戏里面所有得到的 reward 都加起来,就是 `total reward`,我们称其为`return(回报)`,用 R 来表示它。 -* Actor 要想办法去最大化它可以得到的 reward。 +* 一场游戏叫做一个 `回合(episode)` 或者 `试验(trial)`。 +* 把这场游戏里面所有得到的奖励都加起来,就是 `总奖励(total reward)`,我们称其为`回报(return)`,用 R 来表示它。 +* 演员 要想办法去最大化它可以得到的奖励。 ![](img/4.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 觉得说应该要停止为止。 +首先,`环境` 是一个`函数`,游戏的主机也可以把它看作是一个函数,虽然它不一定是神经网络,可能是基于规则的(rule-based)规则,但你可以把它看作是一个函数。这个函数,一开始就先吐出一个状态,也就是游戏的画面,接下来你的演员看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 环境把 $a_1$ 当作它的输入,然后它再吐出 $s_2$,吐出新的游戏画面。演员看到新的游戏画面,再采取新的行为 $a_2$,然后 环境再看到 $a_2$,再吐出 $s_3$。这个过程会一直持续下去,直到 环境觉得说应该要停止为止。 -在一场游戏里面,我们把 environment 输出的 $s$ 跟 actor 输出的行为 $a$,把这个 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory`,如下式所示。 +在一场游戏里面,我们把 环境输出的 $s$ 跟演员输出的行为 $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 里面, 发生这样子状况的概率。 +每一个轨迹,你可以计算它发生的概率。假设现在演员的参数已经被给定了话,就是 $\theta$。根据 $\theta$,你其实可以计算某一个轨迹 发生的概率,你可以计算某一个回合,某一个回合里面, 发生这样子状况的概率。 $$ \begin{aligned} @@ -64,48 +64,47 @@ p_{\theta}(\tau) \end{aligned} $$ -怎么算呢,如上式所示。在假设 actor 的参数就是 $\theta$ 的情况下,某一个 trajectory $\tau$ 的概率就是这样算的,你先算 environment 输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你 policy 里面的 network 参数 $\theta$ 所决定的, 它是一个概率,因为你的 policy 的 network 的 output 是一个 distribution,actor 是根据这个 distribution 去做 sample,决定现在实际上要采取的 action是哪一个。接下来 environment 根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟$s_1$ 还是有关系的,下一个游戏画面,跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在 actor 采取的行为 $a_1$,就会产生 $s_2$。 +怎么算呢,如上式所示。在假设演员的参数就是 $\theta$ 的情况下,某一个轨迹 $\tau$ 的概率就是这样算的,你先算 环境输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你策略里面的网络参数 $\theta$ 所决定的, 它是一个概率,因为你的策略的网络的输出是一个分布,演员是根据这个分布去做采样,决定现在实际上要采取的动作是哪一个。接下来环境根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟$s_1$ 还是有关系的,下一个游戏画面,跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在演员采取的行为 $a_1$,就会产生 $s_2$。 -这件事情可能是概率,也可能不是概率,这个取决于 environment,就是主机它内部设定是怎样。看今天这个主机在决定,要输出什么样的游戏画面的时候,有没有概率。因为如果没有概率的话,这个游戏的每次的行为都一样,你只要找到一条 path 就可以过关了,这样感觉是蛮无聊的 。所以游戏里面,通常是还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。Process 就反复继续下去,你就可以计算一个 trajectory $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。 +这件事情可能是概率,也可能不是概率,这个取决于 环境,就是主机它内部设定是怎样。看今天这个主机在决定,要输出什么样的游戏画面的时候,有没有概率。因为如果没有概率的话,这个游戏的每次的行为都一样,你只要找到一条路径就可以过关了,这样感觉是蛮无聊的 。所以游戏里面通常还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。过程就反复继续下去,你就可以计算一个轨迹 $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, 它就会有不同的出现的概率。 +* 一部分是 `环境的行为`, 环境的函数 它内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是 环境, 环境这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。 +* 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$,演员要采取什么样的 $a_t$ 会取决于你演员的参数 $\theta$, 所以这部分是演员可以自己控制的。随着演员的行为不同,每个同样的轨迹, 它就会有不同的出现的概率。 ![](img/4.6.png) -在 reinforcement learning 里面,除了 environment 跟 actor 以外, 还有`reward function`。 +在强化学习里面,除了 环境跟演员以外, 还有`奖励函数(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。 +奖励函数根据在某一个状态采取的某一个动作 决定说现在这个行为可以得到多少的分数。 它是一个函数,给它 $s_1$,$a_1$,它告诉你得到 $r_1$。给它 $s_2$ ,$a_2$,它告诉你得到 $r_2$。 把所有的 $r$ 都加起来,我们就得到了 $R(\tau)$ ,代表某一个轨迹 $\tau$ 的奖励。 -在某一场游戏里面, 某一个 episode 里面,我们会得到 R。**我们要做的事情就是调整 actor 内部的参数 $\theta$, 使得 R 的值越大越好。** 但实际上 reward 并不只是一个 scalar,reward 其实是一个 random variable。R 其实是一个 random variable,因为 actor 在给定同样的 state 会做什么样的行为,这件事情是有随机性的。Environment 在给定同样的 observation 要采取什么样的 action,要产生什么样的 observation,本身也是有随机性的。所以 R 是一个 random variable,你能够计算的,是它的期望值。你能够计算的是说,在给定某一组参数 $\theta$ 的情况下,我们会得到的 R 的期望值是多少。 +在某一场游戏里面, 某一个回合里面,我们会得到 R。**我们要做的事情就是调整演员内部的参数 $\theta$, 使得 R 的值越大越好。** 但实际上奖励并不只是一个标量,奖励其实是一个随机变量。R 其实是一个随机变量,因为演员在给定同样的状态会做什么样的行为,这件事情是有随机性的。环境在给定同样的观测要采取什么样的动作,要产生什么样的观测,本身也是有随机性的。所以 R 是一个随机变量,你能够计算的,是它的期望值。你能够计算的是说,在给定某一组参数 $\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$ 进行求和,就是期望值。给定一个参数,你会得到的期望值。 +这个期望值的算法如上式所示,穷举所有可能的轨迹 $\tau$, 每一个轨迹 $\tau$ 都有一个概率。比如 $\theta$ 是一个很强的模型, 那它都不会死。如果有一个回合很快就死掉了, 它的概率就很小;如果有一个回合都一直没有死, 那它的概率就很大。根据你的 $\theta$, 你可以算出某一个轨迹 $\tau$ 出现的概率,接下来你计算这个 $\tau$ 的总奖励是多少。总奖励使用这个 $\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。 +我们还可以写成上式那样,从 $p_{\theta}(\tau)$ 这个分布采样一个轨迹 $\tau$,然后计算 $R(\tau)$ 的期望值,就是你的期望的奖励。 我们要做的事情就是最大化期望奖励。 ![](img/4.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 ascent)`,因为要让它越大越好,所以是梯度上升。梯度上升在更新参数的时候要加。要进行梯度上升,我们先要计算期望的奖励(expected reward) $\bar{R}$ 的梯度。我们对 $\bar{R}$ 取一个梯度,这里面只有 $p_{\theta}(\tau)$ 是跟 $\theta$ 有关,所以梯度就放在 $p_{\theta}(\tau)$ 这个地方。$R(\tau)$ 这个奖励函数 不需要是 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)$,然后我们可以得到下式: +接下来, 分子分母,上下同乘 $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 。 - + 然后如下式所示, 对 $\tau$ 进行求和,把 $R(\tau)$ 和 $\log p_{\theta}(\tau)$ 这两项使用 $p_{\theta}(\tau)$ 进行加权, 既然使用 $p_{\theta}(\tau)$ 进行加权 ,它们就可以被写成这个期望的形式。也就是你从 $p_{\theta}(\tau)$ 这个分布里面采样 $\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)} \\&= @@ -114,58 +113,58 @@ $$ \end{aligned} $$ -实际上这个 expected value 没有办法算,所以你是用 sample 的方式来 sample 一大堆的 $\tau$。你 sample $N$ 笔 $\tau$, 然后你去计算每一笔的这些 value,然后把它全部加起来,就可以得到你的 gradient。你就可以去 update 你的参数,你就可以去 update 你的 agent,如下式所示。 +实际上这个期望值没有办法算,所以你是用采样的方式来采样一大堆的 $\tau$。你采样 $N$ 笔 $\tau$, 然后你去计算每一笔的这些值,然后把它全部加起来,就可以得到你的梯度。你就可以去更新你的参数,你就可以去更新你的 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)= +注意 $p_{\theta}(\tau)$ 里面有两项,$p(s_{t+1}|s_t,a_t)$ 来自于环境,$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$, 这个 $s_t$ 跟 $a_t$ 它是在整个轨迹 $\tau$ 的里面的某一个状态和动作的对。 -* 假设你在 $s_t$ 执行 $a_t$,最后发现 $\tau$ 的 reward 是正的, 那你就要增加这一项的概率,你就要增加在 $s_t$ 执行 $a_t$ 的概率。 -* 反之,在 $s_t$ 执行 $a_t$ 会导致$\tau$ 的 reward 变成负的, 你就要减少这一项的概率。 +* 假设你在 $s_t$ 执行 $a_t$,最后发现 $\tau$ 的奖励是正的, 那你就要增加这一项的概率,你就要增加在 $s_t$ 执行 $a_t$ 的概率。 +* 反之,在 $s_t$ 执行 $a_t$ 会导致 $\tau$ 的奖励变成负的, 你就要减少这一项的概率。 ![](img/4.8.png) -这个怎么实现呢? 你用 gradient ascent 来 update 你的参数,你原来有一个参数 $\theta$ ,把你的 $\theta$ 加上你的 gradient 这一项,那当然前面要有个 learning rate,learning rate 其实也是要调的,你可用 Adam、RMSProp 等方法对其进行调整。 +这个怎么实现呢? 你用梯度上升来更新你的参数,你原来有一个参数 $\theta$ ,把你的 $\theta$ 加上你的梯度这一项,那当然前面要有个学习率,学习率也是要调整的,你可用 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$ 。 +实际上,要套上面这个公式, 首先你要先收集一大堆的 s 跟 a 的对,你还要知道这些 s 跟 a 在跟环境互动的时候,你会得到多少的奖励。 这些资料怎么收集呢?你要拿你的 agent,它的参数是 $\theta$,去跟环境做互动, 也就是拿你已经训练好的 agent 先去跟环境玩一下,先去跟那个游戏互动一下, 互动完以后,你就会得到一大堆游戏的纪录,你会记录说,今天先玩了第一场,在第一场游戏里面,我们在状态 $s_1$ 采取动作 $a_1$,在状态$s_2$ 采取动作 $a_2$ 。 -玩游戏的时候是有随机性的,所以 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)$。 +玩游戏的时候是有随机性的,所以 agent 本身是有随机性的,在同样状态$s_1$,不是每次都会采取 $a_1$,所以你要记录下来。在状态$s_1^1$ 采取 $a_1^1$,在状态$s_2^1$ 采取 $a_2^1$。整场游戏结束以后,得到的分数是 $R(\tau^1)$。你会采样到另外一笔数据,也就是另外一场游戏。在另外一场游戏里面,你在状态$s_1^2$ 采取 $a_1^2$,在状态 $s_2^2$ 采取 $a_2^2$,然后你采样到的就是 $\tau^2$,得到的奖励是 $R(\tau^2)$。 -你就可以把 sample 到的东西代到这个 gradient 的式子里面,把 gradient 算出来。也就是把这边的每一个 s 跟 a 的 pair 拿进来,算一下它的 log probability 。你计算一下在某一个 state 采取某一个 action 的 log probability,然后对它取 gradient,然后这个 gradient 前面会乘一个 weight,weight 就是这场游戏的 reward。 有了这些以后,你就会去 update 你的 model。 +你就可以把采样到的东西代到这个梯度的式子里面,把梯度算出来。也就是把这边的每一个 s 跟 a 的对拿进来,算一下它的对数概率(log probability)。你计算一下在某一个状态采取某一个动作的对数概率,然后对它取梯度,然后这个梯度前面会乘一个权重,权重就是这场游戏的奖励。 有了这些以后,你就会去更新你的模型。 -Update 完你的 model 以后。你要重新去收集 data,再 update model。这边要注意一下,一般 `policy gradient(PG) ` sample 的 data 就只会用一次。你把这些 data sample 起来,然后拿去 update 参数,这些 data 就丢掉了。接着再重新 sample data,才能够去 update 参数, 等一下我们会解决这个问题。 +更新完你的模型以后。你要重新去收集数据,再更新模型。这边要注意一下,一般 `policy gradient(PG) `采样的数据就只会用一次。你把这些数据采样起来,然后拿去更新参数,这些数据就丢掉了。接着再重新采样数据,才能够去更新参数, 等一下我们会解决这个问题。 ![](img/4.9.png) **接下来讲一些实现细节。** -我们可以把它想成一个分类的问题,在 classification 里面就是 input 一个 image,然后 output 决定说是 10 个 class 里面的哪一个。在做 classification 时,我们要收集一堆 training data,要有 input 跟 output 的 pair。 +我们可以把它想成一个分类的问题,在分类里面就是输入一个图像,然后输出决定说是 10 个类里面的哪一个。在做分类时,我们要收集一堆训练数据,要有输入跟输出的对(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。 +这些训练的数据从哪里来的呢? 做分类的问题时,要有输入和正确的输出。这些训练数据是从采样的过程来的。假设在采样的过程里面,在某一个状态,你采样到你要采取动作 a, 你就把这个动作 a 当作是你的 ground truth。你在这个状态,你采样到要向左。 本来向左这件事概率不一定是最高, 因为你是采样,它不一定概率最高。假设你采样到向左,在训练的时候 你叫告诉机器说,调整网络的参数, 如果看到这个状态,你就向左。在一般的分类问题里面,其实你在实现分类的时候, 你的目标函数都会写成最小化交叉熵(cross entropy),其实最小化交叉熵就是最大化对数似然(log likelihood)。 ![](img/4.10.png) -做 classification 的时候,objective function 就是 maximize 或 minimize 的对象, 因为我们现在是 maximize likelihood,所以其实是 maximize, 你要 maximize 的对象,如下式所示: +做分类的时候,目标函数就是最大化或最小化的对象, 因为我们现在是最大化似然(likelihood),所以其实是最大化, 你要最大化的对象,如下式所示: $$ \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 里调用现成的 function,它就会自动帮你算,然后你就可以把 gradient 计算出来。这是一般的分类问题,RL 唯一不同的地方是 loss 前面乘上一个 weight,这个是整场游戏的时候得到的 total reward R, 它并不是在 state s 采取 action a 的时候得到的 reward。 你要把你的每一笔 training data,都 weighted by 这个 R。然后你用 TensorFlow 或 PyTorch 去帮你算 gradient 就结束了,跟一般 classification 差不多。 +像这种损失函数,你可在 TensorFlow 里调用现成的函数,它就会自动帮你算,然后你就可以把梯度计算出来。这是一般的分类问题,RL 唯一不同的地方是 loss 前面乘上一个权重,这个是整场游戏的时候得到的总奖励 R, 它并不是在状态 s 采取动作 a 的时候得到的奖励。 你要把你的每一笔训练数据,都使用这个 R 进行加权。然后你用 TensorFlow 或 PyTorch 去帮你算梯度就结束了,跟一般分类差不多。 ## Tips 这边有一些在实现的时候,你也许用得上的 tip。 @@ -173,97 +172,97 @@ $$ ![](img/4.11.png) -**第一个 tip 是 add 一个 baseline。** 如果 given state s 采取 action a 会给你整场游戏正面的 reward,就要增加它的概率。如果 state s 执行 action a,整场游戏得到负的 reward,就要减少这一项的概率。 +**第一个 tip 是 add 一个 baseline。** 如果给定状态 s 采取动作 a 会给你整场游戏正的奖励,就要增加它的概率。如果状态s 执行动作 a,整场游戏得到负的奖励,就要减少这一项的概率。 -但在很多游戏里面, reward 总是正的,就是说最低都是 0。比如说打乒乓球游戏, 你的分数就是介于 0 到 21 分之间,所以这个 R 总是正的。假设你直接套用这个式子, 在 training 的时候,告诉 model 说,不管是什么 action 你都应该要把它的概率提升。 在理想上,这么做并不一定会有问题。因为虽然说 R 总是正的,但它正的量总是有大有小,你在玩乒乓球那个游戏里面,得到的 reward 总是正的,但它是介于 0~21分之间,有时候你采取某些 action 可能是得到 0 分,采取某些 action 可能是得到 20 分。 +但在很多游戏里面,奖励总是正的,就是说最低都是 0。比如说打乒乓球游戏, 你的分数就是介于 0 到 21 分之间,所以这个 R 总是正的。假设你直接套用这个式子, 在训练的时候告诉模型说,不管是什么动作你都应该要把它的概率提升。 在理想上,这么做并不一定会有问题。因为虽然说 R 总是正的,但它正的量总是有大有小,你在玩乒乓球那个游戏里面,得到的奖励总是正的,但它是介于 0~21分之间,有时候你采取某些动作 可能是得到 0 分,采取某些动作 可能是得到 20 分。 ![](img/4.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 以后, 它其实就是下降的,上升的多的,才会上升。 +假设你有 3 个动作 a/b/c 可以执行,在某一个状态有 3 个动作 a/b/c可以执行。根据这个式子,你要把这 3 项的概率,对数概率都拉高。 但是它们前面权重的这个 R 是不一样的。 R 是有大有小的,权重小的,它上升的就少,权重多的,它上升的就大一点。 因为这个对数概率,它是一个概率,所以动作 a、b、c 的和要是 0。 所以上升少的,在做完归一化(normalize)以后, 它其实就是下降的,上升的多的,才会上升。 ![1](img/4.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 不要总是正的。 +这是一个理想上的状况,但是实际上,我们是在做采样就本来这边应该是一个期望(expectation),对所有可能的 s 跟 a 的对进行求和。 但你真正在学的时候,当然不可能是这么做的,你只是采样了少量的 s 跟 a 的对而已。 因为我们做的是采样,有一些动作 可能从来都没有采样到。在某一个状态1,虽然可以执行的动作 有 a/b/c 3 个,但你可能只采样到动作 b,你可能只采样到动作 c,你没有采样到动作 a。但现在所有动作 的奖励都是正的,所以根据这个式子,它的每一项的概率都应该要上升。你会遇到的问题是,因为 a 没有被采样到,其它动作 的概率如果都要上升,a 的概率就下降。 所以 a 不一定是一个不好的动作, 它只是没被采样到。但只是因为它没被采样到, 它的概率就会下降,这个显然是有问题的,要怎么解决这个问题呢?你会希望你的奖励不要总是正的。 ![1.](img/4.14.png) -为了解决 reward 总是正的这个问题,你可以把 reward 减掉一项叫做 b,这项 b 叫做 baseline。你减掉这项 b 以后,就可以让 $R(\tau^n)-b$ 这一项, 有正有负。 所以如果得到的 total reward $R(\tau^n)$ 大于 b 的话,就让它的概率上升。如果这个 total reward 小于 b,就算它是正的,正的很小也是不好的,你就要让这一项的概率下降。 如果$R(\tau^n) Date: Sat, 12 Dec 2020 15:04:39 +0800 Subject: [PATCH 02/13] fix ch4 typos --- docs/chapter4/chapter4.md | 72 ++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 31 deletions(-) diff --git a/docs/chapter4/chapter4.md b/docs/chapter4/chapter4.md index 9636ae6..b47a421 100644 --- a/docs/chapter4/chapter4.md +++ b/docs/chapter4/chapter4.md @@ -23,7 +23,7 @@ * 策略一般写成 $\pi$。假设你是用深度学习的技术来做强化学习的话,**策略就是一个网络**。网络里面就有一堆参数, 我们用 $\theta$ 来代表 $\pi$ 的参数。 -* **网络的输入就是现在机器看到的东西**,如果让机器打电玩的话,机器看到的东西就是游戏的画面。机器看到什么东西,会影响你现在训练到底好不好训练。举例来说,在玩游戏的时候, 也许你觉得游戏的画面,前后是相关的,也许你觉得说,你应该让你的策略,看从游戏初始到现在这个时间点,所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子会比较难处理。要让你的机器,你的策略 看到什么样的画面, 这个是你自己决定的。让你知道说给机器看到什么样的游戏画面,可能是比较有效的。 +* **网络的输入就是现在机器看到的东西**,如果让机器打电玩的话,机器看到的东西就是游戏的画面。机器看到什么东西,会影响你现在训练到底好不好训练。举例来说,在玩游戏的时候, 也许你觉得游戏的画面前后是相关的,也许你觉得你应该让你的策略,看从游戏初始到现在这个时间点,所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子会比较难处理。要让你的机器,你的策略看到什么样的画面,这个是你自己决定的。让你知道说给机器看到什么样的游戏画面,可能是比较有效的。 * **输出的就是机器要采取什么样的行为。** * 上图就是具体的例子, @@ -31,7 +31,7 @@ * 输入 就是游戏的画面,它通常是由像素(pixels)所组成的; * 输出就是看看说有哪些选项是你可以去执行的,输出层就有几个神经元。 * 假设你现在可以做的行为有 3 个,输出层就是有 3 个神经元。每个神经元对应到一个可以采取的行为。 - * 输入一个东西后,网络就会给每一个可以采取的行为一个分数。你可以把这个分数当作是概率。演员就是看这个概率的分布,根据这个概率的分布来决定它要采取的行为。比如说 70% 会走 left,20% 走 right,10% 开火等等。概率分布不同,演员采取的行为就会不一样。 + * 输入一个东西后,网络就会给每一个可以采取的行为一个分数。你可以把这个分数当作是概率。演员就是看这个概率的分布,根据这个概率的分布来决定它要采取的行为。比如说 70% 会向左走,20% 向右走,10% 开火等等。概率分布不同,演员采取的行为就会不一样。 ![](img/4.3.png) **接下来用一个例子来说明演员是怎么样跟环境互动的。** @@ -47,9 +47,9 @@ * 演员 要想办法去最大化它可以得到的奖励。 ![](img/4.5.png) -首先,`环境` 是一个`函数`,游戏的主机也可以把它看作是一个函数,虽然它不一定是神经网络,可能是基于规则的(rule-based)规则,但你可以把它看作是一个函数。这个函数,一开始就先吐出一个状态,也就是游戏的画面,接下来你的演员看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 环境把 $a_1$ 当作它的输入,然后它再吐出 $s_2$,吐出新的游戏画面。演员看到新的游戏画面,再采取新的行为 $a_2$,然后 环境再看到 $a_2$,再吐出 $s_3$。这个过程会一直持续下去,直到 环境觉得说应该要停止为止。 +首先,`环境` 是一个`函数`,游戏的主机也可以把它看作是一个函数,虽然它不一定是神经网络,可能是基于规则的(rule-based)规则,但你可以把它看作是一个函数。这个函数,一开始就先吐出一个状态,也就是游戏的画面,接下来你的演员看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 环境把 $a_1$ 当作它的输入,然后它再吐出 $s_2$,吐出新的游戏画面。演员看到新的游戏画面,再采取新的行为 $a_2$,然后 环境再看到 $a_2$,再吐出 $s_3$。这个过程会一直持续下去,直到环境觉得说应该要停止为止。 -在一场游戏里面,我们把 环境输出的 $s$ 跟演员输出的行为 $a$,把这个 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory(轨迹)`,如下式所示。 +在一场游戏里面,我们把环境输出的 $s$ 跟演员输出的行为 $a$,把这个 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory(轨迹)`,如下式所示。 $$ \text { Trajectory } \tau=\left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\} $$ @@ -66,19 +66,19 @@ $$ 怎么算呢,如上式所示。在假设演员的参数就是 $\theta$ 的情况下,某一个轨迹 $\tau$ 的概率就是这样算的,你先算 环境输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你策略里面的网络参数 $\theta$ 所决定的, 它是一个概率,因为你的策略的网络的输出是一个分布,演员是根据这个分布去做采样,决定现在实际上要采取的动作是哪一个。接下来环境根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟$s_1$ 还是有关系的,下一个游戏画面,跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在演员采取的行为 $a_1$,就会产生 $s_2$。 -这件事情可能是概率,也可能不是概率,这个取决于 环境,就是主机它内部设定是怎样。看今天这个主机在决定,要输出什么样的游戏画面的时候,有没有概率。因为如果没有概率的话,这个游戏的每次的行为都一样,你只要找到一条路径就可以过关了,这样感觉是蛮无聊的 。所以游戏里面通常还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。过程就反复继续下去,你就可以计算一个轨迹 $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。 +这件事情可能是概率,也可能不是概率,这个取决于环境,就是主机它内部设定是怎样。看今天这个主机在决定,要输出什么样的游戏画面的时候,有没有概率。因为如果没有概率的话,这个游戏的每次的行为都一样,你只要找到一条路径就可以过关了,这样感觉是蛮无聊的 。所以游戏里面通常还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。过程就反复继续下去,你就可以计算一个轨迹 $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。 **这个概率取决于两部分**, -* 一部分是 `环境的行为`, 环境的函数 它内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是 环境, 环境这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。 +* 一部分是 `环境的行为`, 环境的函数内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是环境, 环境这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。 * 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$,演员要采取什么样的 $a_t$ 会取决于你演员的参数 $\theta$, 所以这部分是演员可以自己控制的。随着演员的行为不同,每个同样的轨迹, 它就会有不同的出现的概率。 ![](img/4.6.png) -在强化学习里面,除了 环境跟演员以外, 还有`奖励函数(reward function)`。 +在强化学习里面,除了环境跟演员以外, 还有`奖励函数(reward function)`。 -奖励函数根据在某一个状态采取的某一个动作 决定说现在这个行为可以得到多少的分数。 它是一个函数,给它 $s_1$,$a_1$,它告诉你得到 $r_1$。给它 $s_2$ ,$a_2$,它告诉你得到 $r_2$。 把所有的 $r$ 都加起来,我们就得到了 $R(\tau)$ ,代表某一个轨迹 $\tau$ 的奖励。 +奖励函数根据在某一个状态采取的某一个动作决定说现在这个行为可以得到多少的分数。 它是一个函数,给它 $s_1$,$a_1$,它告诉你得到 $r_1$。给它 $s_2$ ,$a_2$,它告诉你得到 $r_2$。 把所有的 $r$ 都加起来,我们就得到了 $R(\tau)$ ,代表某一个轨迹 $\tau$ 的奖励。 在某一场游戏里面, 某一个回合里面,我们会得到 R。**我们要做的事情就是调整演员内部的参数 $\theta$, 使得 R 的值越大越好。** 但实际上奖励并不只是一个标量,奖励其实是一个随机变量。R 其实是一个随机变量,因为演员在给定同样的状态会做什么样的行为,这件事情是有随机性的。环境在给定同样的观测要采取什么样的动作,要产生什么样的观测,本身也是有随机性的。所以 R 是一个随机变量,你能够计算的,是它的期望值。你能够计算的是说,在给定某一组参数 $\theta$ 的情况下,我们会得到的 R 的期望值是多少。 $$ @@ -91,7 +91,7 @@ $$ 我们还可以写成上式那样,从 $p_{\theta}(\tau)$ 这个分布采样一个轨迹 $\tau$,然后计算 $R(\tau)$ 的期望值,就是你的期望的奖励。 我们要做的事情就是最大化期望奖励。 ![](img/4.7.png) -怎么最大化期望奖励呢?我们用的是 `梯度上升(gradient ascent)`,因为要让它越大越好,所以是梯度上升。梯度上升在更新参数的时候要加。要进行梯度上升,我们先要计算期望的奖励(expected reward) $\bar{R}$ 的梯度。我们对 $\bar{R}$ 取一个梯度,这里面只有 $p_{\theta}(\tau)$ 是跟 $\theta$ 有关,所以梯度就放在 $p_{\theta}(\tau)$ 这个地方。$R(\tau)$ 这个奖励函数 不需要是 differentiable,我们也可以解接下来的问题。举例来说,如果是在 GAN 里面,$R(\tau)$ 其实是一个 discriminator,它就算是没有办法微分,也无所谓,你还是可以做接下来的运算。 +怎么最大化期望奖励呢?我们用的是 `梯度上升(gradient ascent)`,因为要让它越大越好,所以是梯度上升。梯度上升在更新参数的时候要加。要进行梯度上升,我们先要计算期望的奖励(expected reward) $\bar{R}$ 的梯度。我们对 $\bar{R}$ 取一个梯度,这里面只有 $p_{\theta}(\tau)$ 是跟 $\theta$ 有关,所以梯度就放在 $p_{\theta}(\tau)$ 这个地方。$R(\tau)$ 这个奖励函数不需要是可微分的(differentiable),这个不影响我们解接下来的问题。举例来说,如果是在 GAN 里面,$R(\tau)$ 其实是一个 discriminator,它就算是没有办法微分,也无所谓,你还是可以做接下来的运算。 取梯度之后,我们背一个公式: $$ @@ -104,7 +104,7 @@ $$ \frac{\nabla p_{\theta}(\tau)}{p_{\theta}(\tau)}=\log p_{\theta}(\tau) $$ - 然后如下式所示, 对 $\tau$ 进行求和,把 $R(\tau)$ 和 $\log p_{\theta}(\tau)$ 这两项使用 $p_{\theta}(\tau)$ 进行加权, 既然使用 $p_{\theta}(\tau)$ 进行加权 ,它们就可以被写成这个期望的形式。也就是你从 $p_{\theta}(\tau)$ 这个分布里面采样 $\tau$ 出来, 去计算 $R(\tau)$ 乘上 $\nabla\log p_{\theta}(\tau)$,然后把它对所有可能的 $\tau$ 进行求和,就是这个期望的值(expected value)。 +如下式所示,对 $\tau$ 进行求和,把 $R(\tau)$ 和 $\log p_{\theta}(\tau)$ 这两项使用 $p_{\theta}(\tau)$ 进行加权, 既然使用 $p_{\theta}(\tau)$ 进行加权 ,它们就可以被写成期望的形式。也就是你从 $p_{\theta}(\tau)$ 这个分布里面采样 $\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)} \\&= @@ -113,14 +113,14 @@ $$ \end{aligned} $$ -实际上这个期望值没有办法算,所以你是用采样的方式来采样一大堆的 $\tau$。你采样 $N$ 笔 $\tau$, 然后你去计算每一笔的这些值,然后把它全部加起来,就可以得到你的梯度。你就可以去更新你的参数,你就可以去更新你的 agent,如下式所示。 +实际上这个期望值没有办法算,所以你是用采样的方式来采样一大堆的 $\tau$。你采样 $N$ 笔 $\tau$, 然后你去计算每一笔的这些值,然后把它全部加起来,就可以得到你的梯度。你就可以去更新你的参数,你就可以去更新你的 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)$ 来自于环境,$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)= +注意 $p_{\theta}(\tau)$ 里面有两项,$p(s_{t+1}|s_t,a_t)$ 来自于环境,$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)$。 你可以非常直观的来理解这个部分,也就是在你采样到的数据里面, 你采样到,在某一个状态 $s_t$ 要执行某一个动作 $a_t$, 这个 $s_t$ 跟 $a_t$ 它是在整个轨迹 $\tau$ 的里面的某一个状态和动作的对。 @@ -138,9 +138,9 @@ $$ $$ \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 的对,你还要知道这些 s 跟 a 在跟环境互动的时候,你会得到多少的奖励。 这些资料怎么收集呢?你要拿你的 agent,它的参数是 $\theta$,去跟环境做互动, 也就是拿你已经训练好的 agent 先去跟环境玩一下,先去跟那个游戏互动一下, 互动完以后,你就会得到一大堆游戏的纪录,你会记录说,今天先玩了第一场,在第一场游戏里面,我们在状态 $s_1$ 采取动作 $a_1$,在状态$s_2$ 采取动作 $a_2$ 。 +实际上,要套上面这个公式, 首先你要先收集一大堆的 s 跟 a 的对(pair),你还要知道这些 s 跟 a 在跟环境互动的时候,你会得到多少的奖励。 这些资料怎么收集呢?你要拿你的 agent,它的参数是 $\theta$,去跟环境做互动, 也就是拿你已经训练好的 agent 先去跟环境玩一下,先去跟那个游戏互动一下, 互动完以后,你就会得到一大堆游戏的纪录,你会记录说,今天先玩了第一场,在第一场游戏里面,我们在状态 $s_1$ 采取动作 $a_1$,在状态$s_2$ 采取动作 $a_2$ 。 -玩游戏的时候是有随机性的,所以 agent 本身是有随机性的,在同样状态$s_1$,不是每次都会采取 $a_1$,所以你要记录下来。在状态$s_1^1$ 采取 $a_1^1$,在状态$s_2^1$ 采取 $a_2^1$。整场游戏结束以后,得到的分数是 $R(\tau^1)$。你会采样到另外一笔数据,也就是另外一场游戏。在另外一场游戏里面,你在状态$s_1^2$ 采取 $a_1^2$,在状态 $s_2^2$ 采取 $a_2^2$,然后你采样到的就是 $\tau^2$,得到的奖励是 $R(\tau^2)$。 +玩游戏的时候是有随机性的,所以 agent 本身是有随机性的,在同样状态$s_1$,不是每次都会采取 $a_1$,所以你要记录下来。在状态 $s_1^1$ 采取 $a_1^1$,在状态 $s_2^1$ 采取 $a_2^1$。整场游戏结束以后,得到的分数是 $R(\tau^1)$。你会采样到另外一笔数据,也就是另外一场游戏。在另外一场游戏里面,你在状态 $s_1^2$ 采取 $a_1^2$,在状态 $s_2^2$ 采取 $a_2^2$,然后你采样到的就是 $\tau^2$,得到的奖励是 $R(\tau^2)$。 你就可以把采样到的东西代到这个梯度的式子里面,把梯度算出来。也就是把这边的每一个 s 跟 a 的对拿进来,算一下它的对数概率(log probability)。你计算一下在某一个状态采取某一个动作的对数概率,然后对它取梯度,然后这个梯度前面会乘一个权重,权重就是这场游戏的奖励。 有了这些以后,你就会去更新你的模型。 @@ -150,7 +150,7 @@ $$ **接下来讲一些实现细节。** -我们可以把它想成一个分类的问题,在分类里面就是输入一个图像,然后输出决定说是 10 个类里面的哪一个。在做分类时,我们要收集一堆训练数据,要有输入跟输出的对(pair)。 +我们可以把它想成一个分类的问题,在分类里面就是输入一个图像,然后输出决定说是 10 个类里面的哪一个。在做分类时,我们要收集一堆训练数据,要有输入跟输出的对。 在实现的时候,你就把状态当作是分类器的输入。 你就当在做图像分类的问题,只是现在的类不是说图像里面有什么东西。 现在的类是说,看到这张图像我们要采取什么样的行为,每一个行为就是一个类。比如说第一个类叫做向左,第二个类叫做向右,第三个类叫做开火。 @@ -164,7 +164,11 @@ $$ \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) $$ -像这种损失函数,你可在 TensorFlow 里调用现成的函数,它就会自动帮你算,然后你就可以把梯度计算出来。这是一般的分类问题,RL 唯一不同的地方是 loss 前面乘上一个权重,这个是整场游戏的时候得到的总奖励 R, 它并不是在状态 s 采取动作 a 的时候得到的奖励。 你要把你的每一笔训练数据,都使用这个 R 进行加权。然后你用 TensorFlow 或 PyTorch 去帮你算梯度就结束了,跟一般分类差不多。 +像这种损失函数,你可在 TensorFlow 里调用现成的函数,它就会自动帮你算,然后你就可以把梯度计算出来。这是一般的分类问题,RL 唯一不同的地方是 loss 前面乘上一个权重:整场游戏得到的总奖励 R,它并不是在状态 s 采取动作 a 的时候得到的奖励,如下式所示: +$$ +\frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) +$$ +你要把你的每一笔训练数据,都使用这个 R 进行加权。然后你用 TensorFlow 或 PyTorch 去帮你算梯度就结束了,跟一般分类差不多。 ## Tips 这边有一些在实现的时候,你也许用得上的 tip。 @@ -183,11 +187,11 @@ $$ ![1](img/4.13.png) -这是一个理想上的状况,但是实际上,我们是在做采样就本来这边应该是一个期望(expectation),对所有可能的 s 跟 a 的对进行求和。 但你真正在学的时候,当然不可能是这么做的,你只是采样了少量的 s 跟 a 的对而已。 因为我们做的是采样,有一些动作 可能从来都没有采样到。在某一个状态1,虽然可以执行的动作 有 a/b/c 3 个,但你可能只采样到动作 b,你可能只采样到动作 c,你没有采样到动作 a。但现在所有动作 的奖励都是正的,所以根据这个式子,它的每一项的概率都应该要上升。你会遇到的问题是,因为 a 没有被采样到,其它动作 的概率如果都要上升,a 的概率就下降。 所以 a 不一定是一个不好的动作, 它只是没被采样到。但只是因为它没被采样到, 它的概率就会下降,这个显然是有问题的,要怎么解决这个问题呢?你会希望你的奖励不要总是正的。 +这是一个理想上的状况,但是实际上,我们是在做采样就本来这边应该是一个期望(expectation),对所有可能的 s 跟 a 的对进行求和。 但你真正在学的时候,当然不可能是这么做的,你只是采样了少量的 s 跟 a 的对而已。 因为我们做的是采样,有一些动作 可能从来都没有采样到。在某一个状态,虽然可以执行的动作 有 a/b/c 3 个,但你可能只采样到动作 b,你可能只采样到动作 c,你没有采样到动作 a。但现在所有动作的奖励都是正的,所以根据这个式子,它的每一项的概率都应该要上升。你会遇到的问题是,因为 a 没有被采样到,其它动作 的概率如果都要上升,a 的概率就下降。 所以 a 不一定是一个不好的动作, 它只是没被采样到。但只是因为它没被采样到, 它的概率就会下降,这个显然是有问题的,要怎么解决这个问题呢?你会希望你的奖励不要总是正的。 ![1.](img/4.14.png) -为了解决奖励总是正的这个问题,你可以把奖励减掉一项叫做 b,这项 b 叫做 baseline。你减掉这项 b 以后,就可以让 $R(\tau^n)-b$ 这一项, 有正有负。 所以如果得到的总奖励$R(\tau^n)$ 大于 b 的话,就让它的概率上升。如果这个总奖励小于 b,就算它是正的,正的很小也是不好的,你就要让这一项的概率下降。 如果$R(\tau^n) Date: Sun, 13 Dec 2020 11:17:09 +0800 Subject: [PATCH 03/13] fix ch1 typos --- docs/chapter1/chapter1.md | 91 ++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 44 deletions(-) diff --git a/docs/chapter1/chapter1.md b/docs/chapter1/chapter1.md index dd20976..209715a 100644 --- a/docs/chapter1/chapter1.md +++ b/docs/chapter1/chapter1.md @@ -7,30 +7,31 @@ * **强化学习讨论的问题是一个智能体(agent) 怎么在一个复杂不确定的环境(environment)里面去极大化它能获得的奖励。** * 示意图由两部分组成:agent 和 environment。 -* 在强化学习过程中,agent 跟 environment 一直在交互。Agent 在环境里面获取到状态,agent 会利用这个状态输出一个 action,一个决策。然后这个决策会放到环境之中去,环境会通过这个 agent 采取的决策,输出下一个状态以及当前的这个决策得到的奖励。Agent 的目的就是为了尽可能多地从环境中获取奖励。 +* 在强化学习过程中,agent 跟 environment 一直在交互。Agent 在环境里面获取到状态,agent 会利用这个状态输出一个动作(action),一个决策。然后这个决策会放到环境之中去,环境会通过这个 agent 采取的决策,输出下一个状态以及当前的这个决策得到的奖励。Agent 的目的就是为了尽可能多地从环境中获取奖励。 ![](img/1.2.png) **我们可以把强化学习跟监督学习做一个对比。** -* 举个图片分类的例子,`监督学习( supervised learning)`就是说我们有一大堆标注的数据,比如车、飞机、凳子这些标注的图片,这些图片都要满足 i.i.d 分布,就是它们之间是没有关联的一个分布。 - -* 然后我们训练一个分类器,比如说右边这个神经网络。为了分辨出这个图片是车辆还是飞机,训练过程中,我们把真实的 label 给了这个网络。当这个网络做出一个错误的预测,比如现在输入了汽车的图片,它预测出来是飞机。我们就会直接告诉它,你这个预测是错误的,正确的 label 应该是车。然后我们把这个错误写成一个`损失函数(loss function)`,通过 Backpropagation 来训练这个网络。 +* 举个图片分类的例子,`监督学习(supervised learning)`就是说我们有一大堆标注的数据,比如车、飞机、凳子这些标注的图片,这些图片都要满足独立同分布(i.i.d.),就是它们之间是没有关联的。 +* 然后我们训练一个分类器,比如说右边这个神经网络。为了分辨出这个图片是车辆还是飞机,训练过程中,我们把真实的标签给了这个网络。当这个网络做出一个错误的预测,比如现在输入了汽车的图片,它预测出来是飞机。我们就会直接告诉它,你这个预测是错误的,正确的标签应该是车。然后我们把这个错误写成一个`损失函数(loss function)`,通过反向传播(Backpropagation)来训练这个网络。 * 所以在监督学习过程中,有两个假设: * 输入的数据(标注的数据)都是没有关联的,尽可能没有关联。因为如果有关联的话,这个网络是不好学习的。 - * 我们告诉这个 learner 正确的标签是什么,这样它可以通过正确的标签来修正自己的这个预测。 + * 我们告诉学习器(learner)正确的标签是什么,这样它可以通过正确的标签来修正自己的预测。 + +> 通常假设样本空间中全体样本服从一个未知分布,我们获得的每个样本都是独立地从这个分布上采样获得的,即独立同分布(independent and identically distributed,简称 i.i.d.)。 ![](img/1.3.png) 在强化学习里面,这两点其实都不满足。举一个 Atari Breakout 游戏的例子,这是一个打砖块的游戏,控制木板,然后把这个球反弹到上面来消除这些砖块。 -* 在游戏过程中,大家可以发现这个 agent 得到的观测不是个 i.i.d 的分布,上一帧下一帧其实有非常强的连续性。 +* 在游戏过程中,大家可以发现这个 agent 得到的观测不是个独立同分布的分布,上一帧下一帧其实有非常强的连续性。 * 另外一点,在玩游戏的过程中,你并没有立刻获得这个反馈。比如你现在把这个木板往右移,那么只会使得这个球往上或者往左上去一点,你并不会得到立刻的反馈。所以强化学习这么困难的原因是没有得到很好的反馈,然后你依然希望这个 agent 在这个环境里面学习。 ![](img/1.4.png) -强化学习的训练数据就是这样一个玩游戏的过程。你从第一步开始,采取一个决策,比如说你把这个往右移,接到这个球了。第二步你又做出决策,得到的 training data 是一个玩游戏的序列。 +强化学习的训练数据就是这样一个玩游戏的过程。你从第一步开始,采取一个决策,比如说你把这个往右移,接到这个球了。第二步你又做出决策,得到的训练数据是一个玩游戏的序列。 比如现在是在第三步,你把这个序列放进去,你希望这个网络可以输出一个决策,在当前的这个状态应该输出往右移或者往左移。这里有个问题,就是我们没有标签来说明你现在这个动作是正确还是错误,必须等到这个游戏结束可能,这个游戏可能十秒过后才结束。现在这个动作往左往右到底是不是对最后游戏的结束能赢有帮助,其实是不清楚的的。这里就面临一个`延迟奖励(Delayed Reward)`,所以就使得训练这个网络非常困难。 @@ -38,25 +39,27 @@ **我们对比下强化学习和监督学习。** -* 首先强化学习输入的序列的数据并不是像 supervised learning 里面这些样本都是独立的。 -* 另外一点是 learner 并没有被告诉你每一步正确的行为应该是什么。Learner 需要自己去发现哪些行为可以使得它最后得到这个奖励,只能通过不停地尝试来发现最有利的 action。 - -* 这里还有一点是 agent 获得自己能力的过程中,其实是通过不断地试错(trial-and-error exploration)。Exploration 和 exploitation 是强化学习里面非常核心的一个问题。Exploration 是说你会去尝试一些新的行为,这些新的行为有可能会使你得到更高的奖励,也有可能使你一无所有。Exploitation 说的是你就是就采取你已知的可以获得最大奖励的行为,你就重复执行这个 action 就可以了,因为你已经知道可以获得一定的奖励。因此,我们需要在 exploration 和 exploitation 之间取得一个权衡,这也是在监督学习里面没有的情况。 - +* 首先强化学习输入的序列的数据并不是像监督学习里面这些样本都是独立的。 +* 另外一点是学习器并没有被告诉你每一步正确的行为应该是什么。学习器需要自己去发现哪些行为可以使得它最后得到这个奖励,只能通过不停地尝试来发现最有利的动作。 +* 这里还有一点是 agent 获得自己能力的过程中,其实是通过不断地试错探索(trial-and-error exploration)。 + * 探索(exploration)和利用(exploitation)是强化学习里面非常核心的一个问题。 + * 探索是说你会去尝试一些新的行为,这些新的行为有可能会使你得到更高的奖励,也有可能使你一无所有。 + * 利用就是就采取你已知的可以获得最大奖励的行为,你就重复执行这个动作就可以了,因为你已经知道可以获得一定的奖励。 + * 因此,我们需要在探索和利用之间取得一个权衡,这也是在监督学习里面没有的情况。 * 在强化学习过程中,没有非常强的 supervisor,只有一个`奖励信号(reward signal)`,就是环境会在很久以后告诉你之前你采取的行为到底是不是有效的。Agent 在这个强化学习里面学习的话就非常困难,因为你没有得到即时反馈。当你采取一个行为过后,如果是监督学习,你就立刻可以获得一个指引,就说你现在做出了一个错误的决定,那么正确的决定应该是谁。而在强化学习里面,环境可能会告诉你这个行为是错误的,但是它并没有告诉你正确的行为是什么。而且更困难的是,它可能是在一两分钟过后告诉你错误,它再告诉你之前的行为到底行不行。所以这也是强化学习和监督学习不同的地方。 ![](img/1.6.png)通过跟监督学习比较,我们可以总结出强化学习的一些特征。 * 强化学习有这个 `trial-and-error exploration`,它需要通过探索环境来获取对这个环境的理解。 * 强化学习 agent 会从环境里面获得延迟的奖励(delayed reward)。 -* 在强化学习的训练过程中,时间非常重要。因为你得到的数据都是有这个时间关联的,而不是这个 i.i.d 分布的。在机器学习中,如果观测数据有非常强的关联,其实会使得这个训练非常不稳定。这也是为什么在监督学习中,我们希望 data 尽量是 i.i.d 了,这样就可以消除数据之间的相关性。 +* 在强化学习的训练过程中,时间非常重要。因为你得到的数据都是有这个时间关联的,而不是独立同分布的。在机器学习中,如果观测数据有非常强的关联,其实会使得这个训练非常不稳定。这也是为什么在监督学习中,我们希望数据尽量是独立同分布,这样就可以消除数据之间的相关性。 * Agent 的行为会影响它随后得到的数据,这一点是非常重要的。在我们训练 agent 的过程中,很多时候我们也是通过正在学习的这个 agent 去跟环境交互来得到数据。所以如果在训练过程中,这个 agent 的模型很快死掉了,那会使得我们采集到的数据是非常糟糕的,这样整个训练过程就失败了。所以在强化学习里面一个非常重要的问题就是怎么让这个 agent 的行为一直稳定地提升。 ![](img/1.7.png) 为什么我们关注强化学习,其中非常重要的一点就是强化学习得到的这个模型可以取得超人类的结果。 -* 监督学习获取的这些监督数据,其实是让人来标注的。比如说 ImageNet,这些图片都是人类标注的。那么我们就可以确定这个算法的 upper bound(上限),人类的这个标注结果决定了它永远不可能超越人类。 +* 监督学习获取的这些监督数据,其实是让人来标注的。比如说 ImageNet,这些图片都是人类标注的。那么我们就可以确定这个算法的上限(upper bound),人类的这个标注结果决定了它永远不可能超越人类。 * 但是对于强化学习,它在环境里面自己探索,有非常大的潜力,它可以获得超越人的能力的这个表现,比如说 AlphaGo,谷歌 DeepMind 的 AlphaGo 这样一个强化学习的算法可以把人类最强的棋手都打败。 ![](img/1.8.png) @@ -64,7 +67,7 @@ 这里给大家举一些在现实生活中强化学习的例子。 * 国际象棋是一个强化学习的过程,因为这个棋手就是在做出一个选择来跟对方对战。 -* 在自然界中,羚羊其实也是在做一个强化学习,它刚刚出生的时候,可能都不知道怎么站立,然后它通过 `trial- and-error` 的一个尝试,三十分钟过后,它就可以跑到每小时 36 公里,很快地适应了这个环境。 +* 在自然界中,羚羊其实也是在做一个强化学习,它刚刚出生的时候,可能都不知道怎么站立,然后它通过试错的一个尝试,三十分钟过后,它就可以跑到每小时 36 公里,很快地适应了这个环境。 * 你也可以把股票交易看成一个强化学习的问题,就怎么去买卖来使你的收益极大化。 * 玩雅达利游戏或者一些电脑游戏,也是一个强化学习的过程。 @@ -78,7 +81,7 @@ 在这个 pong 的游戏里面,决策其实就是两个动作:往上或者往下。如果强化学习是通过学习一个 policy network 来分类的话,其实就是输入当前帧的图片,然后 policy network 就会输出所有决策的可能性。 ![](img/1.11.png) -在这种情况下面,对于监督学习的话,我们就可以直接告诉这个 agent 正确的 label 是什么。在这种游戏情况下面,我们并不知道它的正确的标签是什么。 +在这种情况下面,对于监督学习的话,我们就可以直接告诉这个 agent 正确的标签是什么。在这种游戏情况下面,我们并不知道它的正确的标签是什么。 ![](img/1.12.png) 在强化学习里面,我们是通过让它尝试去玩这个游戏,然后直到游戏结束过后,再去说你前面的一系列动作到底是正确还是错误。 @@ -92,14 +95,14 @@ \tau=\left(s_{0}, a_{0}, s_{1}, a_{1}, \ldots\right) $$ -* 最后结束过后,你会知道你到底有没有把这个球击到对方区域,对方没有接住,你是赢了还是输了。我们可以通过观测序列以及 eventual reward 来训练这个 agent ,使它尽可能地采取可以获得这个 eventual reward 的动作。 +* 最后结束过后,你会知道你到底有没有把这个球击到对方区域,对方没有接住,你是赢了还是输了。我们可以通过观测序列以及最终奖励(eventual reward)来训练这个 agent ,使它尽可能地采取可以获得这个最终奖励的动作。 * 一场游戏叫做一个 `episode(回合)` 或者 `trial(试验)`。 ![](img/1.14.png) 强化学习是有一定的历史的,只是最近大家把强化学习跟深度学习结合起来,就形成了`深度强化学习(Deep Reinforcemet Learning)`。这里做一个类比,把它类比于这个传统的计算机视觉以及深度计算机视觉。 -* 传统的计算机视觉由两个过程组成。你给一张图,我们先要提取它的特征,用一些设计好的 feature,比如说 HOG、DPM。提取这些 feature 后,我们再单独训练一个分类器。这个分类器可以是 SVM、Boosting,然后就可以辨别这张图片是狗还是猫。 +* 传统的计算机视觉由两个过程组成。你给一张图,我们先要提取它的特征,用一些设计好的特征(feature),比如说 HOG、DPM。提取这些特征后,我们再单独训练一个分类器。这个分类器可以是 SVM、Boosting,然后就可以辨别这张图片是狗还是猫。 * 2012 年过后,我们有了卷积神经网络,大家就把特征提取以及分类两者合到一块儿去了,就是训练一个神经网络。这个神经网络既可以做特征提取,也可以做分类。它可以实现这种端到端的训练,它里面的参数可以在每一个阶段都得到极大的优化,这样就得到了一个非常重要的突破。 @@ -108,7 +111,7 @@ 我们可以把神经网络放到强化学习里面。 * 之前的强化学习,比如 TD-Gammon 玩 backgammon 这个游戏,它其实是设计特征,然后通过训练价值函数的一个过程,就是它先设计了很多手工的特征,这个手工特征可以描述现在整个状态。得到这些特征过后,它就可以通过训练一个分类网络或者分别训练一个价值估计函数来做出决策。 -* 现在我们有了深度学习,有了神经网络,那么大家也把这个过程改进成一个 end-to-end training 的过程。你直接输入这个状态,我们不需要去手工地设计这个特征,就可以让它直接输出 action。那么就可以用一个神经网络来拟合我们这里的 value function 或 policy network,省去 了 feature engineering 的过程。 +* 现在我们有了深度学习,有了神经网络,那么大家也把这个过程改进成一个端到端训练(end-to-end training)的过程。你直接输入这个状态,我们不需要去手工地设计这个特征,就可以让它直接输出动作。那么就可以用一个神经网络来拟合我们这里的价值函数或策略网络,省去了特征工程(feature engineering)的过程。 ![](img/1.16.png) @@ -123,10 +126,10 @@ ![](img/1.17.png) 接下来给大家再看一些强化学习里面比较有意思的例子。 -* **第一个例子是 DeepMind 研发的一个走路的 agent。**这个 agent 往前走一步,你就会得到一个 reward。这个 agent 有不同的这个形态,可以学到很多有意思的功能。比如怎么跨越这个障碍物,就像那个蜘蛛那样的 agent 。怎么跨越障碍物,像这个人有双腿一样, 这个 agent 往前走。以及像这个人形 的agent,怎么在一个曲折的道路上面往前走。这个结果也是非常有意思,这个人形 agent 会把手举得非常高,因为它这个手的功能就是为了使它身体保持平衡,这样它就可以更快地在这个环境里面往前跑,而且这里你也可以增加这个环境的难度,加入一些扰动,这个 agent 就会变得更鲁棒。 +* **第一个例子是 DeepMind 研发的一个走路的 agent。**这个 agent 往前走一步,你就会得到一个 reward。这个 agent 有不同的这个形态,可以学到很多有意思的功能。比如怎么跨越这个障碍物,就像那个蜘蛛那样的 agent 。怎么跨越障碍物,像这个人有双腿一样, 这个 agent 往前走。以及像这个人形的 agent,怎么在一个曲折的道路上面往前走。这个结果也是非常有意思,这个人形 agent 会把手举得非常高,因为它这个手的功能就是为了使它身体保持平衡,这样它就可以更快地在这个环境里面往前跑,而且这里你也可以增加这个环境的难度,加入一些扰动,这个 agent 就会变得更鲁棒。 * **第二个例子是机械臂抓取。**因为这个机械臂的应用自动去强化学习需要大量的 rollout,所以它这里就有好多机械臂,分布式系统可以让这个机械臂尝试抓取不同的物体。你发现这个盘子里面物体的形状、形态其实都是不同的,这样就可以让这个机械臂学到一个统一的行为。然后在不同的抓取物下面都可以采取最优的一个抓取特征。你的这个抓取的物件形态存在很多不同,一些传统的这个抓取算法就没法把所有物体都抓起来,因为你对每一个物体都需要做一个建模,这样的话就是非常花时间。但是通过强化学习,你就可以学到一个统一的抓取算法,在不同物体上它都可以适用。 * **第三个例子是 OpenAI 做的一个机械臂翻魔方**。这里它们 18 年的时候先设计了这个手指的一个机械臂,让它可以通过翻动手指,使得手中的这个木块达到一个预定的设定。人的手指其实非常精细,怎么使得这个机械手臂也具有这样灵活的能力就一直是个问题。它们通过这个强化学习在一个虚拟环境里面先训练,让 agent 能翻到特定的这个方向,再把它应用到真实的手臂之中。这在强化学习里面是一个比较常用的做法,就是你先在虚拟环境里面得到一个很好的 agent,然后再把它使用到真实的这个机器人中。因为真实的机械手臂通常都是非常容易坏,而且非常贵,你没法大批量地购买。2019 年对手臂进一步改进了,这个手臂可以玩魔方了。这个结果也非常有意思,到后面,这个魔方就被恢复成了个六面都是一样的结构了。 -* **第四个例子是一个穿衣服的 agent ,就是训练这个 agent 穿衣服。**因为很多时候你要在电影或者一些动画实现这个人穿衣的这种场景,通过手写执行命令让机器人穿衣服其实非常困难。很多时候穿衣服也是一个非常精细的操作,那么它们这个工作就是训练这个强化学习 agent,然后就可以实现这个穿衣功能。这里你还可以加入一些扰动,然后 agent 可以抗扰动。可能有这种 failure case, agent 就穿不进去,就卡在这个地方。 +* **第四个例子是一个穿衣服的 agent ,就是训练这个 agent 穿衣服。**因为很多时候你要在电影或者一些动画实现这个人穿衣的这种场景,通过手写执行命令让机器人穿衣服其实非常困难。很多时候穿衣服也是一个非常精细的操作,那么它们这个工作就是训练这个强化学习 agent,然后就可以实现这个穿衣功能。这里你还可以加入一些扰动,然后 agent 可以抗扰动。可能有这种失败的情况(failure case), agent 就穿不进去,就卡在这个地方。 ## Introduction to Sequential Decision Making @@ -159,7 +162,7 @@ 在一个强化学习环境里面,agent 的目的就是选取一系列的动作来极大化它的奖励,所以这些采取的动作必须有长期的影响。但在这个过程里面,它的奖励其实是被延迟了,就是说你现在采取的某一步决策可能要等到时间很久过后才知道这一步到底产生了什么样的影响。 -这里一个示意图就是我们玩这个 Atari 的 Pong 游戏,你可能只有到最后游戏结束过后,才知道这个球到底有没有击打过去。中间你采取的 up 或 down 行为,并不会直接产生奖励。强化学习里面一个重要的课题就是近期奖励和远期奖励的一个 trade-off。怎么让 agent 取得更多的长期奖励是强化学习的问题。 +这里一个示意图就是我们玩这个 Atari 的 Pong 游戏,你可能只有到最后游戏结束过后,才知道这个球到底有没有击打过去。中间你采取的 up 或 down 行为,并不会直接产生奖励。强化学习里面一个重要的课题就是近期奖励和远期奖励的一个权衡(trade-off)。怎么让 agent 取得更多的长期奖励是强化学习的问题。 ![](img/1.22.png) 在跟环境的交互过程中,agent 会获得很多观测。在每一个观测会采取一个动作,它也会得到一个奖励。**所以历史是观测、行为、奖励的序列:** @@ -200,7 +203,7 @@ POMDP 可以用一个 7 元组描述:$(S,A,T,R,\Omega,O,\gamma)$,其中 $S$ ![](img/1.25.png) 对于一个强化学习 agent,它有如下组成成分: -* 首先 agent 有一个 `policy function`,agent 会用这个函数来选取下一步的动作。 +* 首先 agent 有一个 `策略函数(policy function)`,agent 会用这个函数来选取下一步的动作。 * 然后它也可能生成一个`价值函数(value function)`。我们用价值函数来对当前状态进行估价,它就是说你进入现在这个状态,可以对你后面的收益带来多大的影响。当这个价值函数大的时候,说明你进入这个状态越有利。 @@ -217,7 +220,7 @@ Policy 决定了这个 agent 的行为,它其实是一个函数,把输入的 * 一种是 `deterministic policy(确定性策略)`,就是说你这里有可能只是采取它的极大化,采取最有可能的动作。你现在这个概率就是事先决定好的。 -从 Atari 游戏来看的话,policy function 的输入就是游戏的一帧,它的输出决定你是往左走或者是往右走。 +从 Atari 游戏来看的话,策略函数的输入就是游戏的一帧,它的输出决定你是往左走或者是往右走。 通常情况下,强化学习一般使用`随机性策略`。随机性策略有很多优点: @@ -229,7 +232,7 @@ Policy 决定了这个 agent 的行为,它其实是一个函数,把输入的 ![](img/1.27.png) **价值函数是未来奖励的一个预测,用来评估状态的好坏**。 -价值函数里面有一个 `discount factor`,我们希望尽可能在短的时间里面得到尽可能多的奖励。如果我们说十天过后,我给你 100 块钱,跟我现在给你 100 块钱,你肯定更希望我现在就给你 100 块钱,因为你可以把这 100 块钱存在银行里面,你就会有一些利息。所以我们就通过把这个 discount factor 放到价值函数的定义里面,价值函数的定义其实是一个期望。这里有一个期望 $\mathbb{E}_{\pi}$,这里有个小角标是 $\pi$ 函数,这个 $\pi$ 函数就是说在我们已知某一个 policy function 的时候,到底可以得到多少的奖励。 +价值函数里面有一个 `discount factor(折扣因子)`,我们希望尽可能在短的时间里面得到尽可能多的奖励。如果我们说十天过后,我给你 100 块钱,跟我现在给你 100 块钱,你肯定更希望我现在就给你 100 块钱,因为你可以把这 100 块钱存在银行里面,你就会有一些利息。所以我们就通过把这个折扣因子放到价值函数的定义里面,价值函数的定义其实是一个期望。这里有一个期望 $\mathbb{E}_{\pi}$,这里有个小角标是 $\pi$ 函数,这个 $\pi$ 函数就是说在我们已知某一个策略函数的时候,到底可以得到多少的奖励。 我们还有一种价值函数:Q 函数。Q 函数里面包含两个变量:状态和动作。所以你未来可以获得多少的奖励,它的这个期望取决于你当前的状态和当前的行为。这个 Q 函数是强化学习算法里面要学习的一个函数。因为当我们得到这个 Q 函数后,进入某一种状态,它最优的行为就可以通过这个 Q 函数来得到。 @@ -237,9 +240,9 @@ Policy 决定了这个 agent 的行为,它其实是一个函数,把输入的 ![](img/1.28.png) 第三个组成部分是模型,**模型决定了下一个状态会是什么样的,就是说下一步的状态取决于你当前的状态以及你当前采取的行为。**它由两个部分组成, -* 一个是 probability,它这个转移状态之间是怎么转移的。 +* 概率:这个转移状态之间是怎么转移的。 -* 另外是这个奖励函数,当你在当前状态采取了某一个行为,可以得到多大的奖励。 +* 奖励函数:当你在当前状态采取了某一个行为,可以得到多大的奖励。 ![](img/1.29.png) @@ -274,7 +277,7 @@ Policy 决定了这个 agent 的行为,它其实是一个函数,把输入的 **根据强化学习 agent 的不同,我们可以把 agent 进行归类。** * `基于价值的 agent(value-based agent)`。这一类 agent 显式地学习的是价值函数,隐式地学习了它的策略。策略是从我们学到的价值函数里面推算出来的。 -* `基于策略的 agent(policy-based agent)`。这一类 agent 直接去学习 policy,就是说你直接给它一个 state,它就会输出这个动作的概率。在这个 policy-based agent 里面并没有去学习它的价值函数。 +* `基于策略的 agent(policy-based agent)`。这一类 agent 直接去学习 policy,就是说你直接给它一个状态,它就会输出这个动作的概率。在这个 policy-based agent 里面并没有去学习它的价值函数。 * 把 value-based 和 policy-based 结合起来就有了 `Actor-Critic agent`。这一类 agent 把它的策略函数和价值函数都学习了,然后通过两者的交互得到一个最佳的行为。 Q: 基于策略迭代和基于价值迭代的强化学习方法有什么区别? @@ -291,7 +294,7 @@ A: 对于一个状态转移概率已知的马尔可夫决策过程,我们可 **另外,我们是可以通过 agent 到底有没有学习这个环境模型来分类。** * 第一种是 `model-based(有模型)` RL agent,它通过学习这个状态的转移来采取动作。 -* 另外一种是 ` model-free(免模型)` RL agent,它没有去直接估计这个状态的转移,也没有得到环境的具体转移变量。它通过学习 value function 和 policy function 进行决策。Model-free 的模型里面没有一个环境转移的模型。 +* 另外一种是 ` model-free(免模型)` RL agent,它没有去直接估计这个状态的转移,也没有得到环境的具体转移变量。它通过学习价值函数和策略函数进行决策。Model-free 的模型里面没有一个环境转移的模型。 我们可以用马尔可夫决策过程来定义强化学习任务,并表示为四元组 $$,即状态集合、动作集合、状态转移函数和奖励函数。如果这四元组中所有元素均已知,且状态集合和动作集合在有限步数内是有限集,则机器可以对真实环境进行建模,构建一个虚拟世界来模拟真实环境的状态和交互反应。 @@ -326,7 +329,7 @@ A: 针对是否需要对真实环境建模,强化学习可以分为有模型 ![](img/1.36.png) -把几类模型放到同一个饼图里面。饼图有三个组成部分:value function、policy、model。按一个 agent 具不具有三者中的两者或者一者可以把它分成很多类。 +把几类模型放到同一个饼图里面。饼图有三个组成部分:价值函数、策略和模型。按一个 agent 具不具有三者中的两者或者一者可以把它分成很多类。 ## Learning and Planning @@ -336,7 +339,7 @@ Learning 和 Planning 是序列决策的两个基本问题。 ![](img/learning.png) -在 reinforcement learning 中,环境初始时是未知的,agent 不知道环境如何工作,agent 通过不断地与环境交互,逐渐改进策略。 +在强化学习中,环境初始时是未知的,agent 不知道环境如何工作,agent 通过不断地与环境交互,逐渐改进策略。 ### Planning @@ -353,29 +356,29 @@ Learning 和 Planning 是序列决策的两个基本问题。 ![](img/1.37.png) 在强化学习里面,`Exploration` 和` Exploitation` 是两个很核心的问题。 -* Exploration 是说我们怎么去探索这个环境,通过尝试不同的行为来得到一个最佳的策略,得到最大奖励的策略。 +* 探索是说我们怎么去探索这个环境,通过尝试不同的行为来得到一个最佳的策略,得到最大奖励的策略。 -* Exploitation 是说我们不去尝试新的东西,就采取已知的可以得到很大奖励的行为。 +* 利用是说我们不去尝试新的东西,就采取已知的可以得到很大奖励的行为。 -因为在刚开始的时候强化学习 agent 不知道它采取了某个行为会发生什么,所以它只能通过试错去探索。所以 Exploration 就是在试错来理解采取的这个行为到底可不可以得到好的奖励。Exploitation 是说我们直接采取已知的可以得到很好奖励的行为。所以这里就面临一个 trade-off,怎么通过牺牲一些短期的 reward 来获得行为的理解。 +因为在刚开始的时候强化学习 agent 不知道它采取了某个行为会发生什么,所以它只能通过试错去探索。所以 探索就是在试错来理解采取的这个行为到底可不可以得到好的奖励。利用是说我们直接采取已知的可以得到很好奖励的行为。所以这里就面临一个权衡,怎么通过牺牲一些短期的奖励来获得行为的理解。 ![](img/1.38.png) -这里我给大家举一些例子来说明 Exploration 和 Exploitation 的定义。 +这里我给大家举一些例子来说明探索和利用的定义。 * 以选择餐馆为例, - * Exploitation 是说我们直接去你最喜欢的餐馆,因为你去过这个餐馆很多次了,所以你知道这里面的菜都非常可口。 - * Exploration 是说你把手机拿出来,你直接搜索一个新的餐馆,然后去尝试它到底好不好吃。这里的结果就是有可能这个新的餐馆非常不满意,你就这个钱就浪费了。 + * 利用:我们直接去你最喜欢的餐馆,因为你去过这个餐馆很多次了,所以你知道这里面的菜都非常可口。 + * 探索:你把手机拿出来,你直接搜索一个新的餐馆,然后去尝试它到底好不好吃。这里的结果就是有可能这个新的餐馆非常不满意,你就这个钱就浪费了。 * 以做广告为例, - * Exploitation 就是说我们直接采取最优的这个广告策略。 - * Exploration 就是说我们换一种广告方式,然后看这个新的广告策略到底可不可以得到奖励。 + * 利用:我们直接采取最优的这个广告策略。 + * 探索:我们换一种广告方式,然后看这个新的广告策略到底可不可以得到奖励。 * 以挖油为例, - * Exploitation 就是说我们直接在已知的地方挖油,我们就可以确保挖到油。 - * Exploration 就是说我们在一个新的地方挖油,就有很大的概率,你可能不能发现任何油,但也可能有比较小的概率可以发现一个非常大的油田。 + * 利用:我们直接在已知的地方挖油,我们就可以确保挖到油。 + * 探索:我们在一个新的地方挖油,就有很大的概率,你可能不能发现任何油,但也可能有比较小的概率可以发现一个非常大的油田。 * 以玩游戏为例, - * Exploitation 就是说你总是采取某一种策略。比如说,你可能打街霸,你采取的策略可能是蹲在角落,然后一直触脚。这个策略很可能可以奏效,但可能遇到特定的对手就失效。 - * Exploration 就是说你可能尝试一些新的招式,有可能你会发出大招来,这样就可能一招毙命。 + * 利用:你总是采取某一种策略。比如说,你可能打街霸,你采取的策略可能是蹲在角落,然后一直触脚。这个策略很可能可以奏效,但可能遇到特定的对手就失效。 + * 探索:你可能尝试一些新的招式,有可能你会发出大招来,这样就可能一招毙命。 ### K-armed Bandit ![](img/1.39.png ':size=450') @@ -436,7 +439,7 @@ $python ![](img/1.45.png) -强化学习的这个交互就是由 agent 跟环境进行交互。所以算法的 interface 也是用这个来表示。比如说我们现在安装了 OpenAI Gym。那我们这里就可以直接调入 Taxi-v2 的环境,就建立了这个环境。初始化这个环境过后,就可以进行交互了。Agent 得到这个观测过后,它就会输出一个 action。然后这个 action 会被这个环境拿进去执行这个 step,然后环境就会往前走一步,然后返回新的 observation 和 reward 以及一个 flag variable 就决定你这个游戏是不是结束了。几行代码就实现了强化学习里面的 framework。 +强化学习的这个交互就是由 agent 跟环境进行交互。所以算法的 interface 也是用这个来表示。比如说我们现在安装了 OpenAI Gym。那我们这里就可以直接调入 Taxi-v2 的环境,就建立了这个环境。初始化这个环境过后,就可以进行交互了。Agent 得到这个观测过后,它就会输出一个 action。然后这个动作会被这个环境拿进去执行这个 step,然后环境就会往前走一步,然后返回新的 observation 和 reward 以及一个 flag variable 就决定你这个游戏是不是结束了。几行代码就实现了强化学习里面的 framework。 ![](img/1.46.png) 在 OpenAI Gym 里面有很经典的控制类游戏。 From c457de07dc7dac87e0ed46dfb4dc2f43b9110e70 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Sun, 13 Dec 2020 11:29:22 +0800 Subject: [PATCH 04/13] fix ch1 typos --- docs/chapter1/chapter1.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/chapter1/chapter1.md b/docs/chapter1/chapter1.md index 209715a..de33706 100644 --- a/docs/chapter1/chapter1.md +++ b/docs/chapter1/chapter1.md @@ -260,13 +260,13 @@ Policy 决定了这个 agent 的行为,它其实是一个函数,把输入的 ![](img/1.31.png) * 我们可以用不同的强化学习算法来解这个环境。 -* 如果我们采取的是 `Policy-based RL`,当我们学习好了这个环境过后,在每一个状态,我们就会得到一个最佳的行为。 +* 如果采取的是 `基于策略的(policy-based)RL`,当学习好了这个环境过后,在每一个状态,我们就会得到一个最佳的行为。 * 比如说现在在第一格开始的时候,我们知道它最佳行为是往右走,然后第二格的时候,得到的最佳策略是往上走,第三格是往右走。通过这个最佳的策略,我们就可以最快地到达终点。 ![](img/1.32.png) -* 如果换成 `value-based RL` 这个算法,利用价值函数来作为导向,我们就会得到另外一种表征,这里就表征了你每一个状态会返回一个价值。 +* 如果换成 `基于价值的(value-based)RL` 这个算法,利用价值函数来作为导向,我们就会得到另外一种表征,这里就表征了你每一个状态会返回一个价值。 * 比如说你在 start 位置的时候,价值是 -16,因为你最快可以 16 步到达终点。因为每走一步会减一,所以你这里的价值是 -16。 * 当我们快接近最后终点的时候,这个数字变得越来越大。在拐角的时候,比如要现在在第二格 -15。然后 agent 会看上下,它看到上面值变大了,变成 -14 了,它下面是 -16,那么 agent 肯定就会采取一个往上走的策略。所以通过这个学习的值的不同,我们可以抽取出现在最佳的策略。 @@ -327,7 +327,7 @@ A: 针对是否需要对真实环境建模,强化学习可以分为有模型 * 免模型学习更为简单直观且有丰富的开源资料,像 DQN、AlphaGo 系列等都采用免模型学习; * 在目前的强化学习研究中,大部分情况下环境都是静态的、可描述的,智能体的状态是离散的、可观察的(如 Atari 游戏平台),这种相对简单确定的问题并不需要评估状态转移函数和奖励函数,直接采用免模型学习,使用大量的样本进行训练就能获得较好的效果。 -![](img/1.36.png) +![](img/1.36.png ':size=400') 把几类模型放到同一个饼图里面。饼图有三个组成部分:价值函数、策略和模型。按一个 agent 具不具有三者中的两者或者一者可以把它分成很多类。 @@ -354,7 +354,7 @@ Learning 和 Planning 是序列决策的两个基本问题。 ## Exploration and Exploitation ![](img/1.37.png) -在强化学习里面,`Exploration` 和` Exploitation` 是两个很核心的问题。 +在强化学习里面,`探索` 和`利用` 是两个很核心的问题。 * 探索是说我们怎么去探索这个环境,通过尝试不同的行为来得到一个最佳的策略,得到最大奖励的策略。 @@ -401,9 +401,7 @@ Learning 和 Planning 是序列决策的两个基本问题。 ![](img/1.40.png) 强化学习是一个理论跟实践结合的机器学习分支,需要去推导很多算法公式。然后去理解它算法背后的一些数学原理。另外一方面,上机实践通过实现算法,在很多实验环境里面去探索这个算法是不是可以得到预期效果也是一个非常重要的过程。 -![](img/1.41.png) - -在[这个链接](https://github.com/cuhkrlcourse/RLexample)里面,我其实公布了一些 RL 相关的代码,利用了 Python 和深度学习的一些包(主要是用 PyTorch 为主)。 +在[这个链接](https://github.com/cuhkrlcourse/RLexample)里面,公布了一些 RL 相关的代码,利用了 Python 和深度学习的一些包(主要是用 PyTorch 为主)。 ![](img/1.42.png) From 9c41bc8025bf896413c41b7e9def5d7e3e2df7a9 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Mon, 14 Dec 2020 22:28:30 +0800 Subject: [PATCH 05/13] fix ch1 typos --- docs/chapter1/chapter1.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/chapter1/chapter1.md b/docs/chapter1/chapter1.md index de33706..da2f853 100644 --- a/docs/chapter1/chapter1.md +++ b/docs/chapter1/chapter1.md @@ -119,7 +119,7 @@ 这由几点组成: -* 我们有了更多的计算能力,有了更多的 GPU,可以更快地做更多的 trial-and-error 的尝试。 +* 我们有了更多的计算能力,有了更多的 GPU,可以更快地做更多的试错的尝试。 * 通过这种不同尝试使得 agent 在这个环境里面获得很多信息,然后可以在这个环境里面取得很大的奖励。 * 我们有了这个端到端的一个训练,可以把特征提取和价值估计或者决策一块来优化,这样就可以得到了一个更强的决策网络。 @@ -127,7 +127,7 @@ 接下来给大家再看一些强化学习里面比较有意思的例子。 * **第一个例子是 DeepMind 研发的一个走路的 agent。**这个 agent 往前走一步,你就会得到一个 reward。这个 agent 有不同的这个形态,可以学到很多有意思的功能。比如怎么跨越这个障碍物,就像那个蜘蛛那样的 agent 。怎么跨越障碍物,像这个人有双腿一样, 这个 agent 往前走。以及像这个人形的 agent,怎么在一个曲折的道路上面往前走。这个结果也是非常有意思,这个人形 agent 会把手举得非常高,因为它这个手的功能就是为了使它身体保持平衡,这样它就可以更快地在这个环境里面往前跑,而且这里你也可以增加这个环境的难度,加入一些扰动,这个 agent 就会变得更鲁棒。 -* **第二个例子是机械臂抓取。**因为这个机械臂的应用自动去强化学习需要大量的 rollout,所以它这里就有好多机械臂,分布式系统可以让这个机械臂尝试抓取不同的物体。你发现这个盘子里面物体的形状、形态其实都是不同的,这样就可以让这个机械臂学到一个统一的行为。然后在不同的抓取物下面都可以采取最优的一个抓取特征。你的这个抓取的物件形态存在很多不同,一些传统的这个抓取算法就没法把所有物体都抓起来,因为你对每一个物体都需要做一个建模,这样的话就是非常花时间。但是通过强化学习,你就可以学到一个统一的抓取算法,在不同物体上它都可以适用。 +* **第二个例子是机械臂抓取。**因为机械臂的应用自动去强化学习需要大量的 rollout,所以它这里就有好多机械臂,分布式系统可以让这个机械臂尝试抓取不同的物体。你发现这个盘子里面物体的形状、形态其实都是不同的,这样就可以让这个机械臂学到一个统一的行为。然后在不同的抓取物下面都可以采取最优的一个抓取特征。你的这个抓取的物件形态存在很多不同,一些传统的这个抓取算法就没法把所有物体都抓起来,因为你对每一个物体都需要做一个建模,这样的话就是非常花时间。但是通过强化学习,你就可以学到一个统一的抓取算法,在不同物体上它都可以适用。 * **第三个例子是 OpenAI 做的一个机械臂翻魔方**。这里它们 18 年的时候先设计了这个手指的一个机械臂,让它可以通过翻动手指,使得手中的这个木块达到一个预定的设定。人的手指其实非常精细,怎么使得这个机械手臂也具有这样灵活的能力就一直是个问题。它们通过这个强化学习在一个虚拟环境里面先训练,让 agent 能翻到特定的这个方向,再把它应用到真实的手臂之中。这在强化学习里面是一个比较常用的做法,就是你先在虚拟环境里面得到一个很好的 agent,然后再把它使用到真实的这个机器人中。因为真实的机械手臂通常都是非常容易坏,而且非常贵,你没法大批量地购买。2019 年对手臂进一步改进了,这个手臂可以玩魔方了。这个结果也非常有意思,到后面,这个魔方就被恢复成了个六面都是一样的结构了。 * **第四个例子是一个穿衣服的 agent ,就是训练这个 agent 穿衣服。**因为很多时候你要在电影或者一些动画实现这个人穿衣的这种场景,通过手写执行命令让机器人穿衣服其实非常困难。很多时候穿衣服也是一个非常精细的操作,那么它们这个工作就是训练这个强化学习 agent,然后就可以实现这个穿衣功能。这里你还可以加入一些扰动,然后 agent 可以抗扰动。可能有这种失败的情况(failure case), agent 就穿不进去,就卡在这个地方。 @@ -145,7 +145,7 @@ ### Reward ![](img/1.19.png) -**奖励是由环境给的一个反馈信号**,这个信号指定了这个 agent 在某一步采取了某个策略是否得到奖励。强化学习的目的就是为了极大化 agent 可以获得的奖励,agent 在这个环境里面存在的目的就是为了极大它的期望积累的奖励。 +**奖励是由环境给的一个反馈信号**,这个信号指定了这个 agent 在某一步采取了某个策略是否得到奖励。强化学习的目的就是为了最大化 agent 可以获得的奖励,agent 在这个环境里面存在的目的就是为了极大它的期望积累的奖励。 ![](img/1.20.png) @@ -327,7 +327,7 @@ A: 针对是否需要对真实环境建模,强化学习可以分为有模型 * 免模型学习更为简单直观且有丰富的开源资料,像 DQN、AlphaGo 系列等都采用免模型学习; * 在目前的强化学习研究中,大部分情况下环境都是静态的、可描述的,智能体的状态是离散的、可观察的(如 Atari 游戏平台),这种相对简单确定的问题并不需要评估状态转移函数和奖励函数,直接采用免模型学习,使用大量的样本进行训练就能获得较好的效果。 -![](img/1.36.png ':size=400') +![](img/1.36.png ':size=500') 把几类模型放到同一个饼图里面。饼图有三个组成部分:价值函数、策略和模型。按一个 agent 具不具有三者中的两者或者一者可以把它分成很多类。 From a5198093a9564584460369d51c4b9670661b00aa Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Wed, 16 Dec 2020 10:59:18 +0800 Subject: [PATCH 06/13] fix ch1 typos --- docs/chapter1/chapter1.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/chapter1/chapter1.md b/docs/chapter1/chapter1.md index da2f853..773c4a4 100644 --- a/docs/chapter1/chapter1.md +++ b/docs/chapter1/chapter1.md @@ -33,7 +33,7 @@ 强化学习的训练数据就是这样一个玩游戏的过程。你从第一步开始,采取一个决策,比如说你把这个往右移,接到这个球了。第二步你又做出决策,得到的训练数据是一个玩游戏的序列。 -比如现在是在第三步,你把这个序列放进去,你希望这个网络可以输出一个决策,在当前的这个状态应该输出往右移或者往左移。这里有个问题,就是我们没有标签来说明你现在这个动作是正确还是错误,必须等到这个游戏结束可能,这个游戏可能十秒过后才结束。现在这个动作往左往右到底是不是对最后游戏的结束能赢有帮助,其实是不清楚的的。这里就面临一个`延迟奖励(Delayed Reward)`,所以就使得训练这个网络非常困难。 +比如现在是在第三步,你把这个序列放进去,你希望这个网络可以输出一个决策,在当前的这个状态应该输出往右移或者往左移。这里有个问题:我们没有标签来说明你现在这个动作是正确还是错误,必须等到游戏结束才可能说明,这个游戏可能十秒过后才结束。现在这个动作到底对最后游戏结束能赢是否有帮助,其实是不清楚的。这里就面临`延迟奖励(Delayed Reward)`,所以就使得训练这个网络非常困难。 ![](img/1.5.png) @@ -46,12 +46,12 @@ * 探索是说你会去尝试一些新的行为,这些新的行为有可能会使你得到更高的奖励,也有可能使你一无所有。 * 利用就是就采取你已知的可以获得最大奖励的行为,你就重复执行这个动作就可以了,因为你已经知道可以获得一定的奖励。 * 因此,我们需要在探索和利用之间取得一个权衡,这也是在监督学习里面没有的情况。 -* 在强化学习过程中,没有非常强的 supervisor,只有一个`奖励信号(reward signal)`,就是环境会在很久以后告诉你之前你采取的行为到底是不是有效的。Agent 在这个强化学习里面学习的话就非常困难,因为你没有得到即时反馈。当你采取一个行为过后,如果是监督学习,你就立刻可以获得一个指引,就说你现在做出了一个错误的决定,那么正确的决定应该是谁。而在强化学习里面,环境可能会告诉你这个行为是错误的,但是它并没有告诉你正确的行为是什么。而且更困难的是,它可能是在一两分钟过后告诉你错误,它再告诉你之前的行为到底行不行。所以这也是强化学习和监督学习不同的地方。 +* 在强化学习过程中,没有非常强的监督者(supervisor),只有一个`奖励信号(reward signal)`,就是环境会在很久以后告诉你之前你采取的行为到底是不是有效的。Agent 在这个强化学习里面学习的话就非常困难,因为你没有得到即时反馈。当你采取一个行为过后,如果是监督学习,你就立刻可以获得一个指引,就说你现在做出了一个错误的决定,那么正确的决定应该是谁。而在强化学习里面,环境可能会告诉你这个行为是错误的,但是它并没有告诉你正确的行为是什么。而且更困难的是,它可能是在一两分钟过后告诉你错误,它再告诉你之前的行为到底行不行。所以这也是强化学习和监督学习不同的地方。 ![](img/1.6.png)通过跟监督学习比较,我们可以总结出强化学习的一些特征。 -* 强化学习有这个 `trial-and-error exploration`,它需要通过探索环境来获取对这个环境的理解。 -* 强化学习 agent 会从环境里面获得延迟的奖励(delayed reward)。 +* 强化学习有这个 `试错探索(trial-and-error exploration)`,它需要通过探索环境来获取对这个环境的理解。 +* 强化学习 agent 会从环境里面获得延迟的奖励。 * 在强化学习的训练过程中,时间非常重要。因为你得到的数据都是有这个时间关联的,而不是独立同分布的。在机器学习中,如果观测数据有非常强的关联,其实会使得这个训练非常不稳定。这也是为什么在监督学习中,我们希望数据尽量是独立同分布,这样就可以消除数据之间的相关性。 * Agent 的行为会影响它随后得到的数据,这一点是非常重要的。在我们训练 agent 的过程中,很多时候我们也是通过正在学习的这个 agent 去跟环境交互来得到数据。所以如果在训练过程中,这个 agent 的模型很快死掉了,那会使得我们采集到的数据是非常糟糕的,这样整个训练过程就失败了。所以在强化学习里面一个非常重要的问题就是怎么让这个 agent 的行为一直稳定地提升。 @@ -246,7 +246,7 @@ Policy 决定了这个 agent 的行为,它其实是一个函数,把输入的 ![](img/1.29.png) -当我们有了这三个成分过后,就形成了一个 `Markov Decision Process`。这个决策过程可视化了状态之间的转移以及采取的行为。 +当我们有了这三个组成部分过后,就形成了一个 `马尔可夫决策过程(Markov Decision Process)`。这个决策过程可视化了状态之间的转移以及采取的行为。 ![](img/1.30.png) From 7047bd9b26cbe9216a8b52a391f9959957c81781 Mon Sep 17 00:00:00 2001 From: xyw5vplus1 <53569770+xyw5vplus1@users.noreply.github.com> Date: Thu, 17 Dec 2020 19:56:44 +0800 Subject: [PATCH 07/13] Update chapter3.md --- docs/chapter3/chapter3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/chapter3/chapter3.md b/docs/chapter3/chapter3.md index 9286872..339a0be 100644 --- a/docs/chapter3/chapter3.md +++ b/docs/chapter3/chapter3.md @@ -272,8 +272,8 @@ $$ -* TD 可以从不完整序列上进行学习。 -* TD 只能从完整的序列上进行学习。 +* TD 可以从不完整序列上进行学习。 +* MC 只能从完整的序列上进行学习。 From 207d468686c6720db91d755da5865e88badeafe7 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Thu, 17 Dec 2020 20:32:32 +0800 Subject: [PATCH 08/13] fix ch3 typos --- docs/chapter3/chapter3.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/chapter3/chapter3.md b/docs/chapter3/chapter3.md index 9286872..59021c1 100644 --- a/docs/chapter3/chapter3.md +++ b/docs/chapter3/chapter3.md @@ -70,7 +70,7 @@ MDP 就是序列决策这样一个经典的表达方式。MDP 也是强化学习 ![](img/3.5.png)Q: 为什么可以用未来的总收益来评价当前这个动作是好是坏? -A: 举个例子,假设一辆车在路上,当前是红灯,我们直接走的收益就很低,因为违反交通规则,这就是当前的单步收益。可是如果我们这是一辆救护车,我们正在运送病人,把病人快速送达医院的收益非常的高,而且越快你的收益越大。在这种情况下,我们很可能应该要闯红灯,因为未来的远期收益太高了。这也是为什么强化学习需要去学习远期的收益,因为在现实世界中奖励往往是延迟的,是有 delay 的。所以我们一般会从当前状态开始,把后续有可能会收到所有收益加起来计算当前动作的 Q 的价值,让 Q 的价值可以真正地代表当前这个状态下,动作的真正的价值。 +A: 举个例子,假设一辆车在路上,当前是红灯,我们直接走的收益就很低,因为违反交通规则,这就是当前的单步收益。可是如果我们这是一辆救护车,我们正在运送病人,把病人快速送达医院的收益非常的高,而且越快你的收益越大。在这种情况下,我们很可能应该要闯红灯,因为未来的远期收益太高了。这也是为什么强化学习需要去学习远期的收益,因为在现实世界中奖励往往是延迟的。所以我们一般会从当前状态开始,把后续有可能会收到所有收益加起来计算当前动作的 Q 的价值,让 Q 的价值可以真正地代表当前这个状态下,动作的真正的价值。 ![](img/3.6.png) @@ -267,7 +267,7 @@ $$ ![](img/TD_4.png) -* TD 可以 online learning,每走一步就可以更新,效率高。 +* TD 可以在线学习(online learning),每走一步就可以更新,效率高。 * MC 必须等游戏结束才可以学习。 From c9fd2e0fab4be55d7772464d51dc9e875afd4611 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Sat, 19 Dec 2020 21:37:03 +0800 Subject: [PATCH 09/13] fix ch2 typos --- docs/chapter2/chapter2.md | 57 ++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/docs/chapter2/chapter2.md b/docs/chapter2/chapter2.md index 543c80a..4c8e7b5 100644 --- a/docs/chapter2/chapter2.md +++ b/docs/chapter2/chapter2.md @@ -1,7 +1,5 @@ # MDP -![](img/2.1.png) - 本章给大家介绍马尔可夫决策过程。 * 在介绍马尔可夫决策过程之前,先介绍它的简化版本:马尔可夫链以及马尔可夫奖励过程,通过跟这两种过程的比较,我们可以更容易理解马尔可夫决策过程。 @@ -83,7 +81,7 @@ $$ 这里我们进一步定义一些概念。 -* `Horizon` 是指一个 episode 的长度(每个 episode 最大的时间步数),它是由有限个步数决定的。 +* `Horizon` 是指一个回合的长度(每个回合最大的时间步数),它是由有限个步数决定的。 * `Return(回报)` 说的是把奖励进行折扣后所获得的收益。Return 可以定义为奖励的逐步叠加,如下式所示: @@ -113,7 +111,7 @@ $G_t$ 是之前定义的 `discounted return`,我们这里取了一个期望, * 在人的行为里面来说的话,大家也是想得到即时奖励。 * 有些时候可以把这个系数设为 0,设为 0 过后,我们就只关注了它当前的奖励。我们也可以把它设为 1,设为 1 的话就是对未来并没有折扣,未来获得的奖励跟当前获得的奖励是一样的。 -这个系数可以作为强化学习 agent 的一个 hyperparameter 来进行调整,然后就会得到不同行为的 agent。 +Discount factor 可以作为强化学习 agent 的一个超参数来进行调整,然后就会得到不同行为的 agent。 ![](img/2.11.png) @@ -143,8 +141,8 @@ $$ * $s'$ 可以看成未来的所有状态。 * 转移 $P(s'|s)$ 是指从当前状态转移到未来状态的概率。 -* 第二部分可以看成是一个 Discounted sum of future reward。 * $V(s')$ 代表的是未来某一个状态的价值。我们从当前这个位置开始,有一定的概率去到未来的所有状态,所以我们要把这个概率也写上去,这个转移矩阵也写上去,然后我们就得到了未来状态,然后再乘以一个 $\gamma$,这样就可以把未来的奖励打折扣。 +* 第二部分可以看成是未来奖励的折扣总和(Discounted sum of future reward)。 **Bellman Equation 定义了当前状态跟未来状态之间的这个关系。** @@ -233,14 +231,17 @@ $$ 接下来我们来求解这个价值函数。**我们可以通过迭代的方法来解这种状态非常多的 MRP,**比如说: * 动态规划的方法, -* 蒙特卡罗的办法(通过采样的办法去计算它), -* Temporal-Difference Learning 的办法。 `Temporal-Difference Learning` 叫 `TD Leanring`,它是动态规划和蒙特卡罗的一个结合。 +* 蒙特卡罗的办法(通过采样的办法去计算它), +* 时序差分学习(Temporal-Difference Learning)的办法。 `Temporal-Difference Learning` 叫 `TD Leanring`,它是动态规划和蒙特卡罗的一个结合。 ![](img/2.16.png) -**首先我们用蒙特卡罗(Monte Carlo)的办法来计算它的价值函数。**蒙特卡罗就跟我们之前采用的这个方法很类似,就说我们当得到一个 MRP 过后,我们可以从某一个状态开始,把这个小船放进去,让它随波逐流,这样就会产生一个轨迹。产生了一个轨迹过后,就会得到一个奖励,那么就直接把它的 discounted 的奖励 $g$ 算出来。算出来过后就可以把它积累起来,得到 return $G_t$。 当积累到一定的轨迹数量过后,直接用 $G_t$ 除以轨迹数量,就会得到它的价值。 +**首先我们用蒙特卡罗(Monte Carlo)的办法来计算它的价值函数。**蒙特卡罗就是说当得到一个 MRP 过后,我们可以从某一个状态开始,把这个小船放进去,让它随波逐流,这样就会产生一个轨迹。产生了一个轨迹过后,就会得到一个奖励,那么就直接把它的折扣的奖励 $g$ 算出来。算出来过后就可以把它积累起来,得到 return $G_t$。 当积累到一定的轨迹数量过后,直接用 $G_t$ 除以轨迹数量,就会得到它的价值。 -比如说我们要算 $s_4$ 状态的一个价值。我们就可以从 $s_4$ 状态开始,随机产生很多轨迹,就产生很多小船,然后扔到这个转移矩阵里面去,然后它就会随波逐流,产生轨迹。每个轨迹,我们可以算到它的这个 return。每个轨迹都会得到一个 return,让我们得到大量的 return 。比如说一百个、一千个的 return ,然后直接取一个平均,那么就可以等价于现在 $s_4$ 这个价值,因为 $s_4$ 的价值 $V(s_4)$ 定义了你未来可能得到多少的奖励。这就是蒙特卡罗采样的方法。 +比如说我们要算 $s_4$ 状态的价值。 + +* 我们就可以从 $s_4$ 状态开始,随机产生很多轨迹,就是说产生很多小船,把小船扔到这个转移矩阵里面去,然后它就会随波逐流,产生轨迹。 +* 每个轨迹都会得到一个 return,我们得到大量的 return,比如说一百个、一千个 return ,然后直接取一个平均,那么就可以等价于现在 $s_4$ 这个价值,因为 $s_4$ 的价值 $V(s_4)$ 定义了你未来可能得到多少的奖励。这就是蒙特卡罗采样的方法。 ![](img/2.17.png)**我们也可以用这个动态规划的办法**,一直去迭代它的 Bellman equation,让它最后收敛,我们就可以得到它的一个状态。所以在这里算法二就是一个迭代的算法,通过 bootstrapping(拔靴自助) 的办法,然后去不停地迭代这个 Bellman Equation。当这个最后更新的状态跟你上一个状态变化并不大的时候,更新就可以停止,我们就可以输出最新的 $V'(s)$ 作为它当前的状态。所以这里就是把 Bellman Equation 变成一个 Bellman Update,这样就可以得到它的一个价值。 @@ -254,7 +255,7 @@ $$ **相对于 MRP,`马尔可夫决策过程(Markov Decision Process)`多了一个 `decision`,其它的定义跟 MRP 都是类似的**: -* 这里多了一个决策,多了一个 action。 +* 这里多了一个决策,多了一个动作。 * 状态转移也多了一个条件,变成了 $P\left(s_{t+1}=s^{\prime} \mid s_{t}=s, a_{t}=a\right)$。你采取某一种动作,然后你未来的状态会不同。未来的状态不仅是依赖于你当前的状态,也依赖于在当前状态 agent 采取的这个动作。 * 对于这个价值函数,它也是多了一个条件,多了一个你当前的这个动作,变成了 $R\left(s_{t}=s, a_{t}=a\right)=\mathbb{E}\left[r_{t} \mid s_{t}=s, a_{t}=a\right]$。你当前的状态以及你采取的动作会决定你在当前可能得到的奖励多少。 @@ -447,7 +448,7 @@ $$ * 假设环境里面有两种动作:往左走和往右走。 * 现在的奖励函数应该是关于动作以及状态两个变量的一个函数。但我们这里规定,不管你采取什么动作,只要到达状态 $s_1$,就有 5 的奖励。只要你到达状态 $s_7$ 了,就有 10 的奖励,中间没有任何奖励。 -* 假设我们现在采取的一个策略,这个策略是说不管在任何状态,我们采取的策略都是往左走。假设价值折扣因子是零,那么对于 deterministic policy,最后估算出的价值函数是一致的,即 +* 假设我们现在采取的一个策略,这个策略是说不管在任何状态,我们采取的策略都是往左走。假设价值折扣因子是零,那么对于确定性策略(deterministic policy),最后估算出的价值函数是一致的,即 $$ V^{\pi}=[5,0,0,0,0,0,10] @@ -527,7 +528,7 @@ MDP 是满足动态规划的要求的, * 在 Bellman equation 里面,我们可以把它分解成一个递归的结构。当我们把它分解成一个递归的结构的时候,如果我们的子问题子状态能得到一个值,那么它的未来状态因为跟子状态是直接相连的,那我们也可以继续推算出来。 * 价值函数就可以储存并重用它的最佳的解。 -动态规划应用于 MDP 的规划问题(planning)而不是学习问题(learning),我们必须对环境是完全已知的(Model-Based),才能做动态规划,直观的说,就是要知道状态转移概率和对应的 reward 才行 +动态规划应用于 MDP 的规划问题(planning)而不是学习问题(learning),我们必须对环境是完全已知的(Model-Based),才能做动态规划,直观的说,就是要知道状态转移概率和对应的奖励才行 动态规划能够完成预测问题和控制问题的求解,是解 MDP prediction 和 control 一个非常有效的方式。 @@ -566,18 +567,16 @@ $$ * 这个 agent 采取的动作,它的 policy function 就直接先给定了,它在每一个状态都是随机游走,它们在每一个状态就是上下左右行走。它在边缘状态的时候,比如说在第四号状态的时候,它往左走的话,它是依然存在第四号状态,我们加了这个限制。 * 这里我们给的奖励函数就是说你每走一步,就会得到 -1 的奖励,所以 agent 需要尽快地到达终止状态。 -* 状态之间的转移也是确定的。比如从第六号状态往上走,它就会直接到达第二号状态。很多时候有些环境是 `probabilistic` 的话,就是说 agent 在第六号状态,它选择往上走的时候,有可能地板是滑的,然后它可能滑到第三号状态或者第一号状态,这就是有概率的一个转移。但这里把这个环境进行了简化,从六号往上走,它就到了二号。 +* 状态之间的转移也是确定的。比如从第六号状态往上走,它就会直接到达第二号状态。很多时候有些环境是 `概率性的(probabilistic)`, 就是说 agent 在第六号状态,它选择往上走的时候,有可能地板是滑的,然后它可能滑到第三号状态或者第一号状态,这就是有概率的一个转移。但这里把这个环境进行了简化,从六号往上走,它就到了二号。 * 所以直接用这个迭代来解它,因为我们已经知道每一个概率以及它的这个概率转移,那么就直接可以进行一个简短的迭代,这样就会算出它每一个状态的价值。 ![](img/2.36.png) -![](img/2.37.png ':size=550') - 我们再来看一个动态的例子,首先推荐斯坦福大学的一个网站:[GridWorld: Dynamic Programming Demo](https://cs.stanford.edu/people/karpathy/reinforcejs/gridworld_dp.html) ,这个网站模拟了单步更新的过程中,所有格子的一个状态价值的变化过程。 -这里有很多格子,每个格子都代表了一个状态。在每个格子里面有一个初始值零。然后在每一个状态,它还有一些箭头,这个箭头就是说它在当前这个状态应该采取什么样的策略。我们这里采取一个随机的策略,不管它在哪一个状态,它上下左右的概率都是相同的。比如在某个状态,它都有上下左右 0.25 的概率采取某一个动作,所以它的动作是完全随机的。 +![](img/2.37.png ':size=550')这里有很多格子,每个格子都代表了一个状态。在每个格子里面有一个初始值零。然后在每一个状态,它还有一些箭头,这个箭头就是说它在当前这个状态应该采取什么样的策略。我们这里采取一个随机的策略,不管它在哪一个状态,它上下左右的概率都是相同的。比如在某个状态,它都有上下左右 0.25 的概率采取某一个动作,所以它的动作是完全随机的。 -在这样的环境里面,我们想计算它每一个状态的价值。我们也定义了它的 reward function,你可以看到有些状态上面有一个 R 的值。比如我们这边有些值是为负的,我们可以看到格子里面有几个 -1 的 reward,只有一个 +1 reward 的格子。在这个棋盘的中间这个位置,可以看到有一个 R 的值是 1.0,为正的一个价值函数。 所以每个状态对应了一个值,然后有一些状态没有任何值,就说明它的这个 reward function,它的奖励是为零的。 +在这样的环境里面,我们想计算它每一个状态的价值。我们也定义了它的 reward function,你可以看到有些状态上面有一个 R 的值。比如我们这边有些值是为负的,我们可以看到格子里面有几个 -1 的奖励,只有一个 +1 奖励的格子。在这个棋盘的中间这个位置,可以看到有一个 R 的值是 1.0,为正的一个价值函数。 所以每个状态对应了一个值,然后有一些状态没有任何值,就说明它的这个 reward function,它的奖励是为零的。 ![](img/2.38.png ':size=550') @@ -630,11 +629,7 @@ A: 当取得最佳的价值函数过后,我们可以通过对这个 Q 函数 $$ \pi^{*}(s)=\underset{\pi}{\arg \max } ~ v^{\pi}(s) $$ -对于一个事先定好的 MDP 过程,当 agent 去采取最佳策略的时候, - -* 我们可以说最佳策略一般都是确定的。 -* 而且是 stationary,它不会随着时间的变化。 -* 但是不一定是 unique,多种动作可能会取得相同的这个价值。 +对于一个事先定好的 MDP 过程,当 agent 去采取最佳策略的时候,我们可以说最佳策略一般都是确定的,而且是稳定的(它不会随着时间的变化)。但是不一定是唯一的,多种动作可能会取得相同的这个价值。 **我们可以通过 policy iteration 和 value iteration 来解 MDP 的控制问题。** @@ -675,15 +670,15 @@ $$ ![](img/2.47.png) -当一直在采取 arg max 这个操作的时候,我们会得到一个单调的递增。通过采取这种 greedy,即 arg max 操作,我们就会得到更好的或者不变的 policy,而不会使它这个价值函数变差。所以当这个改进停止过后,我们就会得到一个最佳策略。 +当一直在采取 arg max 操作的时候,我们会得到一个单调的递增。通过采取这种 greedy,即 arg max 操作,我们就会得到更好的或者不变的 policy,而不会使它这个价值函数变差。所以当这个改进停止过后,我们就会得到一个最佳策略。 ![](img/2.48.png) -当改进停止过后,我们取它极大化的这个 action,它直接就会变成它的价值函数,即 +当改进停止过后,我们取它最大化的这个 action,它直接就会变成它的价值函数,如下式所示: $$ q^{\pi}\left(s, \pi^{\prime}(s)\right)=\max _{a \in \mathcal{A}} q^{\pi}(s, a)=q^{\pi}(s, \pi(s))=v^{\pi}(s) $$ -所以我们在这里有了一个新的等式: +所以我们有了一个新的等式: $$ v^{\pi}(s)=\max _{a \in \mathcal{A}} q^{\pi}(s, a) $$ @@ -699,7 +694,7 @@ $$ $$ v^{*}(s)=\max _{a} q^{*}(s, a) $$ -当我们取最大的这个 action 的时候对应的那个值就是当前那个状态的最佳的价值函数。 +当我们取最大的这个 action 的时候对应的值就是当前状态的最佳的价值函数。 另外,我们给出第二个等式,即 Q 函数的 Bellman equation: $$ @@ -758,7 +753,7 @@ $$ $$ v(s) \leftarrow \max _{a \in \mathcal{A}}\left(R(s, a)+\gamma \sum_{s^{\prime} \in \mathcal{S}} P\left(s^{\prime} \mid s, a\right) v\left(s^{\prime}\right)\right) $$ -之前我们说上面这个等式只有当整个 MDP 已经到达最佳的状态时才满足。但这里可以把它转换成一个 backup 的等式。 Backup 就是说一个迭代的等式。**我们不停地去迭代 Bellman Optimality Equation,到了最后,它能逐渐趋向于最佳的策略,这是 value iteration 算法的精髓。** +之前我们说上面这个等式只有当整个 MDP 已经到达最佳的状态时才满足。但这里可以把它转换成一个 backup 的等式。Backup 就是说一个迭代的等式。**我们不停地去迭代 Bellman Optimality Equation,到了最后,它能逐渐趋向于最佳的策略,这是 value iteration 算法的精髓。** 为了得到最佳的 $v^*$ ,对于每个状态的 $v^*$,我们直接把这个 Bellman Optimality Equation 进行迭代,迭代了很多次之后,它就会收敛。 @@ -773,8 +768,8 @@ $$ ![](img/2.52.png) * value function 做的工作类似于 value 的反向传播,每次迭代做一步传播,所以中间过程的 policy 和 value function 是没有意义的。不像是 policy iteration,它每一次迭代的结果都是有意义的,都是一个完整的 policy。 -* 上图是一个可视化的过程,在一个 gridworld 中,我们设定了一个终点(goal),也就是左上角的点。不管你在哪一个位置开始,我们都希望能够到终点(实际上这个终点是在迭代过程中不必要的,只是为了更好的演示)。Value iteration 的迭代过程像是一个从某一个 state(这里是我们的 goal)反向传播其他各个状态的过程。因为每次迭代只能影响到与之直接相关的状态。 -* 让我们回忆下 Principle of Optimality Theorem:当你这次迭代求解的某个状态 s 的 value function $v_{k+1}(s)$ 是最优解,它的前提是能够从该状态到达的所有状态 s' 此时都已经得到了最优解;如果不是的话,它做的事情只是一个类似传递 value function 的过程。 +* 上图是一个可视化的过程,在一个 gridworld 中,我们设定了一个终点(goal),也就是左上角的点。不管你在哪一个位置开始,我们都希望能够到终点(实际上这个终点是在迭代过程中不必要的,只是为了更好的演示)。Value iteration 的迭代过程像是一个从某一个状态(这里是我们的 goal)反向传播其他各个状态的过程。因为每次迭代只能影响到与之直接相关的状态。 +* 让我们回忆下 `Principle of Optimality Theorem`:当你这次迭代求解的某个状态 s 的 value function $v_{k+1}(s)$ 是最优解,它的前提是能够从该状态到达的所有状态 s' 此时都已经得到了最优解;如果不是的话,它做的事情只是一个类似传递 value function 的过程。 * 以上图为例,实际上,对于每一个状态,我们都可以看成一个终点。迭代由每一个终点开始,每次都根据 Bellman optimality equation 重新计算 value。如果它的相邻节点 value 发生变化,变得更好,那么它也会变得更好,一直到相邻节点都不变了。因此,**在我们迭代到** $v_7$ **之前,也就是还没将每个终点的最优的 value 传递给其他的所有状态之前,中间的几个 value function 只是一种暂存的不完整的数据,它不能代表每一个 state 的 value function,所以生成的 policy 是一个没有意义的 policy**。 * 因为它是一个迭代过程,这里可视化了从 $v_1$ 到 $v_7$ 每一个状态的值的变化,它的这个值逐渐在变化。而且因为它每走一步,就会得到一个负的值,所以它需要尽快地到达左上角,可以发现离它越远的,那个值就越小。 * $v_7$ 收敛过后,右下角那个值是 -6,相当于它要走六步,才能到达最上面那个值。而且离目的地越近,它的价值越大。 @@ -827,14 +822,14 @@ $$ ![](img/2.62.png ':size=550') -**我们再用 value iteration 来解 MDP,点第 3 个 value iteration。** +**我们再用 value iteration 来解 MDP,点 Toggle value iteration。** * 当它的这个值确定下来过后,它会产生它的最佳状态,这个最佳状态提取的策略跟 policy iteration 得出来的最佳策略是一致的。 * 在每个状态,我们跟着这个最佳策略走,就会到达可以得到最多奖励的一个状态。 ![](img/2.63.png) -[这个 Demo](https://github.com/cuhkrlcourse/RLexample/tree/master/MDP) 里面是一个代码,就是为了解一个叫 `FrozenLake` 的例子,这个例子是 OpenAI Gym 里的一个环境,跟 gridworld 很像,不过它每一个状态转移是一个 probability。 +[这个 Demo](https://github.com/cuhkrlcourse/RLexample/tree/master/MDP) 里面是一个代码,就是为了解一个叫 `FrozenLake` 的例子,这个例子是 OpenAI Gym 里的一个环境,跟 gridworld 很像,不过它每一个状态转移是一个概率。 ![](img/2.64.png) From a875f35760282a4bdae34ca88c9c4d66f2a7b927 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Sat, 19 Dec 2020 21:41:52 +0800 Subject: [PATCH 10/13] fix ch2 typos --- docs/chapter2/chapter2.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/chapter2/chapter2.md b/docs/chapter2/chapter2.md index 4c8e7b5..b9982fc 100644 --- a/docs/chapter2/chapter2.md +++ b/docs/chapter2/chapter2.md @@ -574,7 +574,8 @@ $$ 我们再来看一个动态的例子,首先推荐斯坦福大学的一个网站:[GridWorld: Dynamic Programming Demo](https://cs.stanford.edu/people/karpathy/reinforcejs/gridworld_dp.html) ,这个网站模拟了单步更新的过程中,所有格子的一个状态价值的变化过程。 -![](img/2.37.png ':size=550')这里有很多格子,每个格子都代表了一个状态。在每个格子里面有一个初始值零。然后在每一个状态,它还有一些箭头,这个箭头就是说它在当前这个状态应该采取什么样的策略。我们这里采取一个随机的策略,不管它在哪一个状态,它上下左右的概率都是相同的。比如在某个状态,它都有上下左右 0.25 的概率采取某一个动作,所以它的动作是完全随机的。 +![](img/2.37.png ':size=550') +这里有很多格子,每个格子都代表了一个状态。在每个格子里面有一个初始值零。然后在每一个状态,它还有一些箭头,这个箭头就是说它在当前这个状态应该采取什么样的策略。我们这里采取一个随机的策略,不管它在哪一个状态,它上下左右的概率都是相同的。比如在某个状态,它都有上下左右 0.25 的概率采取某一个动作,所以它的动作是完全随机的。 在这样的环境里面,我们想计算它每一个状态的价值。我们也定义了它的 reward function,你可以看到有些状态上面有一个 R 的值。比如我们这边有些值是为负的,我们可以看到格子里面有几个 -1 的奖励,只有一个 +1 奖励的格子。在这个棋盘的中间这个位置,可以看到有一个 R 的值是 1.0,为正的一个价值函数。 所以每个状态对应了一个值,然后有一些状态没有任何值,就说明它的这个 reward function,它的奖励是为零的。 From 17113221418b580bf815baf4db3950208434fc03 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Sun, 20 Dec 2020 19:50:45 +0800 Subject: [PATCH 11/13] fix ch4 typos --- docs/chapter4/chapter4.md | 45 ++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/docs/chapter4/chapter4.md b/docs/chapter4/chapter4.md index b47a421..fa24844 100644 --- a/docs/chapter4/chapter4.md +++ b/docs/chapter4/chapter4.md @@ -17,7 +17,7 @@ * 环境就是对手; * 奖励函数就是按照围棋的规则, 赢就是得一分,输就是负一分等等。 -在强化学习里面,环境跟奖励函数不是你可以控制的,环境跟奖励函数是在开始学习之前,就已经事先给定的。你唯一能做的事情是调整 演员里面的策略(policy),使得 演员可以得到最大的奖励。演员里面会有一个策略, 这个策略决定了演员的行为。策略就是给一个外界的输入,然后它会输出演员现在应该要执行的行为。 +在强化学习里面,环境跟奖励函数不是你可以控制的,环境跟奖励函数是在开始学习之前,就已经事先给定的。你唯一能做的事情是调整演员里面的策略(policy),使得 演员可以得到最大的奖励。演员里面会有一个策略, 这个策略决定了演员的行为。策略就是给一个外界的输入,然后它会输出演员现在应该要执行的行为。 ![](img/4.2.png) @@ -38,7 +38,7 @@ 首先演员会看到一个游戏画面,我们用 $s_1$ 来表示游戏初始的画面。接下来演员看到这个游戏的初始画面以后,根据它内部的网络,根据它内部的策略来决定一个动作。假设它现在决定的动作 是向右,它决定完动作 以后,它就会得到一个奖励,代表它采取这个动作以后得到的分数。 -我们把一开始的初始画面记作 $s_1$, 把第一次执行的动作记作 $a_1$,把第一次执行动作完以后得到的奖励记作 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$,这个都可以,你自己看得懂就好。演员 决定一个行为以后, 就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给演员,这个演员决定要开火,然后它可能杀了一只怪,就得到五分。这个过程就反复地持续下去,直到今天走到某一个时间点执行某一个动作,得到奖励之后, 这个环境决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。 +我们把一开始的初始画面记作 $s_1$, 把第一次执行的动作记作 $a_1$,把第一次执行动作完以后得到的奖励记作 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$,这个都可以,你自己看得懂就好。演员 决定一个行为以后,就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给演员,这个演员决定要开火,然后它可能杀了一只怪,就得到五分。这个过程就反复地持续下去,直到今天走到某一个时间点执行某一个动作,得到奖励之后, 这个环境决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。 ![](img/4.4.png) @@ -49,12 +49,12 @@ ![](img/4.5.png) 首先,`环境` 是一个`函数`,游戏的主机也可以把它看作是一个函数,虽然它不一定是神经网络,可能是基于规则的(rule-based)规则,但你可以把它看作是一个函数。这个函数,一开始就先吐出一个状态,也就是游戏的画面,接下来你的演员看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 环境把 $a_1$ 当作它的输入,然后它再吐出 $s_2$,吐出新的游戏画面。演员看到新的游戏画面,再采取新的行为 $a_2$,然后 环境再看到 $a_2$,再吐出 $s_3$。这个过程会一直持续下去,直到环境觉得说应该要停止为止。 -在一场游戏里面,我们把环境输出的 $s$ 跟演员输出的行为 $a$,把这个 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory(轨迹)`,如下式所示。 +在一场游戏里面,我们把环境输出的 $s$ 跟演员输出的行为 $a$,把 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory(轨迹)`,如下式所示。 $$ \text { Trajectory } \tau=\left\{s_{1}, a_{1}, s_{2}, a_{2}, \cdots, s_{t}, a_{t}\right\} $$ -每一个轨迹,你可以计算它发生的概率。假设现在演员的参数已经被给定了话,就是 $\theta$。根据 $\theta$,你其实可以计算某一个轨迹 发生的概率,你可以计算某一个回合,某一个回合里面, 发生这样子状况的概率。 +你可以计算每一个轨迹发生的概率。假设现在演员的参数已经被给定了话,就是 $\theta$。根据 $\theta$,你其实可以计算某一个轨迹发生的概率,你可以计算某一个回合里面发生这样子状况的概率。 $$ \begin{aligned} @@ -64,14 +64,14 @@ p_{\theta}(\tau) \end{aligned} $$ -怎么算呢,如上式所示。在假设演员的参数就是 $\theta$ 的情况下,某一个轨迹 $\tau$ 的概率就是这样算的,你先算 环境输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你策略里面的网络参数 $\theta$ 所决定的, 它是一个概率,因为你的策略的网络的输出是一个分布,演员是根据这个分布去做采样,决定现在实际上要采取的动作是哪一个。接下来环境根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟$s_1$ 还是有关系的,下一个游戏画面,跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在演员采取的行为 $a_1$,就会产生 $s_2$。 +怎么算呢,如上式所示。在假设演员的参数就是 $\theta$ 的情况下,某一个轨迹 $\tau$ 的概率就是这样算的,你先算环境输出 $s_1$ 的概率,再计算根据 $s_1$ 执行 $a_1$ 的概率,这是由你策略里面的网络参数 $\theta$ 所决定的, 它是一个概率,因为你的策略的网络的输出是一个分布,演员是根据这个分布去做采样,决定现在实际上要采取的动作是哪一个。接下来环境根据 $a_1$ 跟 $s_1$ 产生 $s_2$,因为 $s_2$ 跟 $s_1$ 还是有关系的,下一个游戏画面跟前一个游戏画面通常还是有关系的,至少要是连续的, 所以给定前一个游戏画面 $s_1$ 和现在演员采取的行为 $a_1$,就会产生 $s_2$。 这件事情可能是概率,也可能不是概率,这个取决于环境,就是主机它内部设定是怎样。看今天这个主机在决定,要输出什么样的游戏画面的时候,有没有概率。因为如果没有概率的话,这个游戏的每次的行为都一样,你只要找到一条路径就可以过关了,这样感觉是蛮无聊的 。所以游戏里面通常还是有一些概率的,你做同样的行为,给同样的前一个画面, 下次产生的画面不见得是一样的。过程就反复继续下去,你就可以计算一个轨迹 $s_1$,$a_1$, $s_2$ , $a_2$ 出现的概率有多大。 **这个概率取决于两部分**, * 一部分是 `环境的行为`, 环境的函数内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是环境, 环境这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。 -* 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$,演员要采取什么样的 $a_t$ 会取决于你演员的参数 $\theta$, 所以这部分是演员可以自己控制的。随着演员的行为不同,每个同样的轨迹, 它就会有不同的出现的概率。 +* 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$,演员要采取什么样的 $a_t$ 会取决于演员的参数 $\theta$, 所以这部分是演员可以自己控制的。随着演员的行为不同,每个同样的轨迹, 它就会有不同的出现的概率。 ![](img/4.6.png) @@ -80,11 +80,18 @@ $$ 奖励函数根据在某一个状态采取的某一个动作决定说现在这个行为可以得到多少的分数。 它是一个函数,给它 $s_1$,$a_1$,它告诉你得到 $r_1$。给它 $s_2$ ,$a_2$,它告诉你得到 $r_2$。 把所有的 $r$ 都加起来,我们就得到了 $R(\tau)$ ,代表某一个轨迹 $\tau$ 的奖励。 -在某一场游戏里面, 某一个回合里面,我们会得到 R。**我们要做的事情就是调整演员内部的参数 $\theta$, 使得 R 的值越大越好。** 但实际上奖励并不只是一个标量,奖励其实是一个随机变量。R 其实是一个随机变量,因为演员在给定同样的状态会做什么样的行为,这件事情是有随机性的。环境在给定同样的观测要采取什么样的动作,要产生什么样的观测,本身也是有随机性的。所以 R 是一个随机变量,你能够计算的,是它的期望值。你能够计算的是说,在给定某一组参数 $\theta$ 的情况下,我们会得到的 R 的期望值是多少。 +在某一场游戏里面, 某一个回合里面,我们会得到 R。**我们要做的事情就是调整演员内部的参数 $\theta$, 使得 R 的值越大越好。** 但实际上奖励并不只是一个标量,奖励其实是一个随机变量。R 其实是一个随机变量,因为演员在给定同样的状态会做什么样的行为,这件事情是有随机性的。环境在给定同样的观测要采取什么样的动作,要产生什么样的观测,本身也是有随机性的,所以 R 是一个随机变量。你能够计算的是 R 的期望值。你能够计算的是说,在给定某一组参数 $\theta$ 的情况下,我们会得到的 $R_{\theta}$ 的期望值是多少。 $$ \bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau) $$ -这个期望值的算法如上式所示,穷举所有可能的轨迹 $\tau$, 每一个轨迹 $\tau$ 都有一个概率。比如 $\theta$ 是一个很强的模型, 那它都不会死。如果有一个回合很快就死掉了, 它的概率就很小;如果有一个回合都一直没有死, 那它的概率就很大。根据你的 $\theta$, 你可以算出某一个轨迹 $\tau$ 出现的概率,接下来你计算这个 $\tau$ 的总奖励是多少。总奖励使用这个 $\tau$ 出现的概率进行加权,对所有的 $\tau$ 进行求和,就是期望值。给定一个参数,你会得到的期望值。 +这个期望值的算法如上式所示。我们要穷举所有可能的轨迹 $\tau$, 每一个轨迹 $\tau$ 都有一个概率。 + +比如 $\theta$ 是一个很强的模型,它都不会死。因为 $\theta$ 很强,所以: + +* 如果有一个回合 $\theta$ 很快就死掉了,因为这种情况很少会发生,所以该回合对应的轨迹 $\tau$ 的概率就很小; +* 如果有一个回合 $\theta$ 都一直没有死,因为这种情况很可能发生,所以该回合对应的轨迹 $\tau$ 的概率就很大。 + +你可以根据 $\theta$ 算出某一个轨迹 $\tau$ 出现的概率,接下来计算这个 $\tau$ 的总奖励是多少。总奖励使用这个 $\tau$ 出现的概率进行加权,对所有的 $\tau$ 进行求和,就是期望值。给定一个参数,你会得到的期望值。 $$ \bar{R}_{\theta}=\sum_{\tau} R(\tau) p_{\theta}(\tau)=E_{\tau \sim p_{\theta}(\tau)}[R(\tau)] $$ @@ -120,10 +127,21 @@ E_{\tau \sim p_{\theta}(\tau)}\left[R(\tau) \nabla \log p_{\theta}(\tau)\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)$ 来自于环境,$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)$。 +下面给出 $\nabla \log p_{\theta}(\tau)$ 的具体计算过程。 +$$ +\nabla \log p_{\theta}(\tau) = \nabla \left(\log p(s_1)+\sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)+ \sum_{t=1}^{T}\log p(s_{t+1}|s_t,a_t) \right) +$$ -你可以非常直观的来理解这个部分,也就是在你采样到的数据里面, 你采样到,在某一个状态 $s_t$ 要执行某一个动作 $a_t$, 这个 $s_t$ 跟 $a_t$ 它是在整个轨迹 $\tau$ 的里面的某一个状态和动作的对。 +注意 $p(s_1)$ 和 $p(s_{t+1}|s_t,a_t)$ 来自于环境,$p_\theta(a_t|s_t)$ 是来自于 agent。$p(s_1)$ 和 $p(s_{t+1}|s_t,a_t)$ 由环境决定,所以与 $\theta$ 无关,因此 $\nabla \log p(s_1)=0$ ,$\nabla \sum_{t=1}^{T}\log p(s_{t+1}|s_t,a_t)=0$,所以: +$$ +\begin{aligned} +\nabla \log p_{\theta}(\tau) &= \nabla \left(\log p(s_1)+\sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)+ \sum_{t=1}^{T}\log p(s_{t+1}|s_t,a_t) \right) \\ +&= \nabla \log p(s_1)+ \nabla \sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)+ \nabla \sum_{t=1}^{T}\log p(s_{t+1}|s_t,a_t) \\ +&=\nabla \sum_{t=1}^{T}\log p_{\theta}(a_t|s_t)\\ +&=\sum_{t=1}^{T} \nabla\log p_{\theta}(a_t|s_t) +\end{aligned} +$$ +你可以非常直观的来理解这个部分,也就是在你采样到的数据里面, 你采样到在某一个状态 $s_t$ 要执行某一个动作 $a_t$, 这个 $s_t$ 跟 $a_t$ 它是在整个轨迹 $\tau$ 的里面的某一个状态和动作的对。 * 假设你在 $s_t$ 执行 $a_t$,最后发现 $\tau$ 的奖励是正的, 那你就要增加这一项的概率,你就要增加在 $s_t$ 执行 $a_t$ 的概率。 * 反之,在 $s_t$ 执行 $a_t$ 会导致 $\tau$ 的奖励变成负的, 你就要减少这一项的概率。 @@ -133,8 +151,7 @@ $$ ![](img/4.8.png) 这个怎么实现呢? 你用梯度上升来更新你的参数,你原来有一个参数 $\theta$ ,把你的 $\theta$ 加上你的梯度这一项,那当然前面要有个学习率,学习率也是要调整的,你可用 Adam、RMSProp 等方法对其进行调整。 -我们可以套下面这个公式来把梯度计算出来: - +我们可以套下面这个公式来把梯度计算出来: $$ \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) $$ @@ -163,7 +180,6 @@ $$ $$ \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) $$ - 像这种损失函数,你可在 TensorFlow 里调用现成的函数,它就会自动帮你算,然后你就可以把梯度计算出来。这是一般的分类问题,RL 唯一不同的地方是 loss 前面乘上一个权重:整场游戏得到的总奖励 R,它并不是在状态 s 采取动作 a 的时候得到的奖励,如下式所示: $$ \frac{1}{N} \sum_{n=1}^{N} \sum_{t=1}^{T_{n}} R\left(\tau^{n}\right) \log p_{\theta}\left(a_{t}^{n} \mid s_{t}^{n}\right) @@ -195,7 +211,6 @@ $$ $$ b \approx E[R(\tau)] $$ - 这是其中一种做法, 你可以想想看有没有其它的做法。 所以在实现训练的时候,你会不断地把 $R(\tau)$ 的分数记录下来 然后你会不断地去计算 $R(\tau)$ 的平均值, 你会把这个平均值,当作你的 b 来用。 这样就可以让你在训练的时候, $\nabla \log p_{\theta}\left(a_{t}^{n} | s_{t}^{n}\right)$ 乘上前面这一项, 是有正有负的,这个是第一个 tip。 From 79fdd06ecac18f62089372b23c11587247ff6645 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Mon, 21 Dec 2020 20:25:41 +0800 Subject: [PATCH 12/13] fix ch4 typos --- docs/chapter4/chapter4.md | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/docs/chapter4/chapter4.md b/docs/chapter4/chapter4.md index fa24844..7f6a4f1 100644 --- a/docs/chapter4/chapter4.md +++ b/docs/chapter4/chapter4.md @@ -21,7 +21,7 @@ ![](img/4.2.png) -* 策略一般写成 $\pi$。假设你是用深度学习的技术来做强化学习的话,**策略就是一个网络**。网络里面就有一堆参数, 我们用 $\theta$ 来代表 $\pi$ 的参数。 +* 策略一般写成 $\pi$。假设你是用深度学习的技术来做强化学习的话,**策略就是一个网络**。网络里面就有一堆参数,我们用 $\theta$ 来代表 $\pi$ 的参数。 * **网络的输入就是现在机器看到的东西**,如果让机器打电玩的话,机器看到的东西就是游戏的画面。机器看到什么东西,会影响你现在训练到底好不好训练。举例来说,在玩游戏的时候, 也许你觉得游戏的画面前后是相关的,也许你觉得你应该让你的策略,看从游戏初始到现在这个时间点,所有画面的总和。你可能会觉得你要用到 RNN 来处理它,不过这样子会比较难处理。要让你的机器,你的策略看到什么样的画面,这个是你自己决定的。让你知道说给机器看到什么样的游戏画面,可能是比较有效的。 * **输出的就是机器要采取什么样的行为。** @@ -38,16 +38,16 @@ 首先演员会看到一个游戏画面,我们用 $s_1$ 来表示游戏初始的画面。接下来演员看到这个游戏的初始画面以后,根据它内部的网络,根据它内部的策略来决定一个动作。假设它现在决定的动作 是向右,它决定完动作 以后,它就会得到一个奖励,代表它采取这个动作以后得到的分数。 -我们把一开始的初始画面记作 $s_1$, 把第一次执行的动作记作 $a_1$,把第一次执行动作完以后得到的奖励记作 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$,这个都可以,你自己看得懂就好。演员 决定一个行为以后,就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给演员,这个演员决定要开火,然后它可能杀了一只怪,就得到五分。这个过程就反复地持续下去,直到今天走到某一个时间点执行某一个动作,得到奖励之后, 这个环境决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。 +我们把一开始的初始画面记作 $s_1$, 把第一次执行的动作记作 $a_1$,把第一次执行动作完以后得到的奖励记作 $r_1$。不同的书会有不同的定义,有人会觉得说这边应该要叫做 $r_2$,这个都可以,你自己看得懂就好。演员决定一个行为以后,就会看到一个新的游戏画面,这边是 $s_2$。然后把这个 $s_2$ 输入给演员,这个演员决定要开火,然后它可能杀了一只怪,就得到五分。这个过程就反复地持续下去,直到今天走到某一个时间点执行某一个动作,得到奖励之后,这个环境决定这个游戏结束了。比如说,如果在这个游戏里面,你是控制绿色的船去杀怪,如果你被杀死的话,游戏就结束,或是你把所有的怪都清空,游戏就结束了。 ![](img/4.4.png) * 一场游戏叫做一个 `回合(episode)` 或者 `试验(trial)`。 * 把这场游戏里面所有得到的奖励都加起来,就是 `总奖励(total reward)`,我们称其为`回报(return)`,用 R 来表示它。 -* 演员 要想办法去最大化它可以得到的奖励。 +* 演员要想办法去最大化它可以得到的奖励。 ![](img/4.5.png) -首先,`环境` 是一个`函数`,游戏的主机也可以把它看作是一个函数,虽然它不一定是神经网络,可能是基于规则的(rule-based)规则,但你可以把它看作是一个函数。这个函数,一开始就先吐出一个状态,也就是游戏的画面,接下来你的演员看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后 环境把 $a_1$ 当作它的输入,然后它再吐出 $s_2$,吐出新的游戏画面。演员看到新的游戏画面,再采取新的行为 $a_2$,然后 环境再看到 $a_2$,再吐出 $s_3$。这个过程会一直持续下去,直到环境觉得说应该要停止为止。 +首先,`环境` 是一个`函数`,游戏的主机也可以把它看作是一个函数,虽然它不一定是神经网络,可能是基于规则的(rule-based)规则,但你可以把它看作是一个函数。这个函数一开始就先吐出一个状态,也就是游戏的画面,接下来你的演员看到这个游戏画面 $s_1$ 以后,它吐出 $a_1$,然后环境把 $a_1$ 当作它的输入,然后它再吐出 $s_2$,吐出新的游戏画面。演员看到新的游戏画面,再采取新的行为 $a_2$,然后 环境再看到 $a_2$,再吐出 $s_3$。这个过程会一直持续下去,直到环境觉得说应该要停止为止。 在一场游戏里面,我们把环境输出的 $s$ 跟演员输出的行为 $a$,把 $s$ 跟 $a$ 全部串起来, 叫做一个 `Trajectory(轨迹)`,如下式所示。 $$ @@ -70,7 +70,7 @@ $$ **这个概率取决于两部分**, -* 一部分是 `环境的行为`, 环境的函数内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是环境, 环境这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。 +* 一部分是 `环境的行为`, 环境的函数内部的参数或内部的规则长什么样子。 $p(s_{t+1}|s_t,a_t)$这一项代表的是环境,环境这一项通常你是无法控制它的,因为那个是人家写好的,你不能控制它。 * 另一部分是 `agent 的行为`。你能控制的是 $p_\theta(a_t|s_t)$。给定一个 $s_t$,演员要采取什么样的 $a_t$ 会取决于演员的参数 $\theta$, 所以这部分是演员可以自己控制的。随着演员的行为不同,每个同样的轨迹, 它就会有不同的出现的概率。 @@ -161,7 +161,7 @@ $$ 你就可以把采样到的东西代到这个梯度的式子里面,把梯度算出来。也就是把这边的每一个 s 跟 a 的对拿进来,算一下它的对数概率(log probability)。你计算一下在某一个状态采取某一个动作的对数概率,然后对它取梯度,然后这个梯度前面会乘一个权重,权重就是这场游戏的奖励。 有了这些以后,你就会去更新你的模型。 -更新完你的模型以后。你要重新去收集数据,再更新模型。这边要注意一下,一般 `policy gradient(PG) `采样的数据就只会用一次。你把这些数据采样起来,然后拿去更新参数,这些数据就丢掉了。接着再重新采样数据,才能够去更新参数, 等一下我们会解决这个问题。 +更新完你的模型以后。你要重新去收集数据,再更新模型。注意,一般 `policy gradient(PG) `采样的数据就只会用一次。你把这些数据采样起来,然后拿去更新参数,这些数据就丢掉了。接着再重新采样数据,才能够去更新参数,等一下我们会解决这个问题。 ![](img/4.9.png) @@ -207,7 +207,7 @@ $$ ![1.](img/4.14.png) -为了解决奖励总是正的这个问题,你可以把奖励减掉一项叫做 b,这项 b 叫做 baseline。你减掉这项 b 以后,就可以让 $R(\tau^n)-b$ 这一项, 有正有负。 所以如果得到的总奖励 $R(\tau^n)$ 大于 b 的话,就让它的概率上升。如果这个总奖励小于 b,就算它是正的,正的很小也是不好的,你就要让这一项的概率下降。 如果$R(\tau^n) 独热编码(one-hot Encoding)通常用于处理类别间不具有大小关系的特征。 例如血型,一共有4个取值(A型、B型、AB型、O型),独热编码会把血型变成一个4维稀疏向量,A型血表示为(1,0,0,0),B型血表示为(0,1,0,0),AB型会表示为(0,0,1,0),O型血表示为(0,0,0,1)。 + * 我们把神经网络的输出和实际动作带入交叉熵的公式就可以求出输出的概率和实际的动作之间的差距。 * 但这个实际的动作 $a_t$ 只是我们输出的真实的动作,它并不一定是正确的动作,它不能像手写数字识别一样作为一个正确的标签来去指导神经网络朝着正确的方向去更新,所以我们需要乘以一个奖励回报 $G_t$。这个奖励回报相当于是对这个真实动作 的评价。 * 如果 $G_t$ 越大,未来总收益越大,那就说明当前输出的这个真实的动作就越好,这个 loss 就越需要重视。 @@ -322,7 +325,7 @@ REINFORCE 的伪代码主要看最后四行,先产生一个回合的数据, ![](img/4.28.png) -上图是 REINFORCE 的流程图。首先我们需要一个 policy model 来输出动作概率,输出动作概率后,我们 sample() 函数去得到一个具体的动作,然后跟环境交互过后,我们可以得到一整个回合的数据。拿到回合数据之后,我再去执行一下 learn() 函数,在 learn() 函数里面,我就可以拿这些数据去构造损失函数,扔给这个优化器去优化,去更新我的 policy model。 +上图是 REINFORCE 的流程图。首先我们需要一个 policy model 来输出动作概率,输出动作概率后,我们 `sample()` 函数去得到一个具体的动作,然后跟环境交互过后,我们可以得到一整个回合的数据。拿到回合数据之后,我再去执行一下 `learn()` 函数,在 `learn()` 函数里面,我就可以拿这些数据去构造损失函数,扔给这个优化器去优化,去更新我的 policy model。 ## References From 0a9c1bd78d3d5d30f6c11c9d43e0e73863cadbf4 Mon Sep 17 00:00:00 2001 From: qiwang067 Date: Mon, 21 Dec 2020 20:30:02 +0800 Subject: [PATCH 13/13] fix ch4 typos --- docs/chapter4/chapter4.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/chapter4/chapter4.md b/docs/chapter4/chapter4.md index 7f6a4f1..1387d05 100644 --- a/docs/chapter4/chapter4.md +++ b/docs/chapter4/chapter4.md @@ -289,11 +289,14 @@ $$ REINFORCE 的伪代码主要看最后四行,先产生一个回合的数据,比如 $(s_1,a_1,G_1),(s_2,a_2,G_2),\cdots,(s_T,a_T,G_T)$。然后针对每个动作 来计算梯度。 在代码上计算时,我们要拿到神经网络的输出。神经网络会输出每个动作对应的概率值,然后我们还可以拿到实际的动作,把它转成 one-hot 向量乘一下,我们可以拿到 $\ln \pi(A_t|S_t,\theta)$ 。 +> 独热编码(one-hot Encoding)通常用于处理类别间不具有大小关系的特征。 例如血型,一共有4个取值(A型、B型、AB型、O型),独热编码会把血型变成一个4维稀疏向量,A型血表示为(1,0,0,0),B型血表示为(0,1,0,0),AB型会表示为(0,0,1,0),O型血表示为(0,0,0,1)。 + ![](img/4.23.png) -* 手写数字识别是一个经典的多分类问题,输入是一张手写数字的图片,经过神经网络输出的是各个分类的一个概率。 +* 手写数字识别是一个经典的多分类问题,输入是一张手写数字的图片,经过神经网络输出的是各个类别的一个概率。 * 目的是希望输出的这个概率的分布尽可能地去贴近真实值的概率分布。 * 因为真实值只有一个数字 9,你用这个 one-hot 向量的形式去给它编码的话,也可以把这个真实值理解为一个概率分布,9 的概率就是1,其他的概率就是 0。 + * 神经的网络输出一开始可能会比较平均,通过不断地迭代,训练优化之后,我会希望 9 输出的概率可以远高于其他数字输出的概率。 ![](img/4.24.png) @@ -311,8 +314,6 @@ REINFORCE 的伪代码主要看最后四行,先产生一个回合的数据, * 类似地,policy gradient 预测每一个状态下面应该要输出的这个行动的概率,就是输入状态 $s_t$,然后输出动作的概率,比如 0.02,0.08,0.09。实际上输出给环境的动作是随机选了一个动作,比如说我选了右这个动作,它的 one-hot 向量就是 0,0,1。 -> 独热编码(one-hot Encoding)通常用于处理类别间不具有大小关系的特征。 例如血型,一共有4个取值(A型、B型、AB型、O型),独热编码会把血型变成一个4维稀疏向量,A型血表示为(1,0,0,0),B型血表示为(0,1,0,0),AB型会表示为(0,0,1,0),O型血表示为(0,0,0,1)。 - * 我们把神经网络的输出和实际动作带入交叉熵的公式就可以求出输出的概率和实际的动作之间的差距。 * 但这个实际的动作 $a_t$ 只是我们输出的真实的动作,它并不一定是正确的动作,它不能像手写数字识别一样作为一个正确的标签来去指导神经网络朝着正确的方向去更新,所以我们需要乘以一个奖励回报 $G_t$。这个奖励回报相当于是对这个真实动作 的评价。 * 如果 $G_t$ 越大,未来总收益越大,那就说明当前输出的这个真实的动作就越好,这个 loss 就越需要重视。