diff --git a/docs/chapter6/chapter6.md b/docs/chapter6/chapter6.md index f5f2fb1..fec5086 100644 --- a/docs/chapter6/chapter6.md +++ b/docs/chapter6/chapter6.md @@ -131,7 +131,7 @@ Q-function 有两种写法: 假设动作是离散的,动作就只有 3 个可能:往左往右或是开火。那这个 Q-function 输出的 3 个值就分别代表 a 是向左的时候的 Q 值,a 是向右的时候的 Q 值,还有 a 是开火的时候的 Q 值。 -那你要注意的事情是,上图右边的函数只有离散动作才能够使用。如果动作是无法穷举的,你只能够用上图左边这个式子,不能够用右边这个式子。 +要注意的事情是,上图右边的函数只有离散动作才能够使用。如果动作是无法穷举的,你只能够用上图左边这个式子,不能够用右边这个式子。 ![](img/6.8.png ':size=550') @@ -192,7 +192,7 @@ $$ $$ V^{\pi}(s) \leq Q^{\pi}\left(s, \pi^{\prime}(s)\right) $$ -也就是说某一个状态,如果你按照策略 $\pi$ 一直做下去,你得到的奖励一定会小于等于,在这个状态 s 你故意不按照 $\pi$ 所给你指示的方向,而是按照 $\pi'$ 的方向走一步,但只有第一步是按照 $\pi'$ 的方向走,只有在状态 s 这个地方,你才按照 $\pi'$ 的指示走,接下来你就按照 $\pi$ 的指示走。虽然只有一步之差, 但是从上面这个式子可知,虽然只有一步之差,但你得到的奖励一定会比完全 follow $\pi$ 得到的奖励还要大。 +也就是说某一个状态,如果按照策略 $\pi$ 一直做下去,你得到的奖励一定会小于等于,在这个状态 s 你故意不按照 $\pi$ 所给你指示的方向,而是按照 $\pi'$ 的方向走一步,但只有第一步是按照 $\pi'$ 的方向走,只有在状态 s 这个地方,你才按照 $\pi'$ 的指示走,接下来你就按照 $\pi$ 的指示走。虽然只有一步之差, 但是从上面这个式子可知,虽然只有一步之差,但你得到的奖励一定会比完全 follow $\pi$ 得到的奖励还要大。 接下来要证下面的式子: $$ @@ -250,13 +250,13 @@ $$ ![](img/6.12.png ':size=550') -接下来讲一下在 DQN 里你一定会用到的 tip。第一个是 `目标网络(target network)`,什么意思呢?我们在学习 Q-function 的时候,也会用到 TD 的概念。那怎么用 TD?你现在收集到一个数据, 是说在状态 $s_t$,你采取动作 $a_t$ 以后,你得到奖励 $r_t$ ,然后跳到状态 $s_{t+1}$。然后根据这个 Q-function,你会知道说 +接下来讲一下在 DQN 里一定会用到的 tip。第一个是 `目标网络(target network)`,什么意思呢?我们在学习 Q-function 的时候,也会用到 TD 的概念。那怎么用 TD?你现在收集到一个数据, 是说在状态 $s_t$,你采取动作 $a_t$ 以后,你得到奖励 $r_t$ ,然后跳到状态 $s_{t+1}$。然后根据这个 Q-function,你会知道说 $$ \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) $$ -所以你在学习的时候,你会说我们有 Q-function,输入 $s_t$, $a_t$ 得到的值,跟输入 $s_{t+1}$, $\pi (s_{t+1})$ 得到的值中间,我们希望它差了一个 $r_t$, 这跟刚才讲的 TD 的概念是一样的。 +所以在学习的时候,你会说我们有 Q-function,输入 $s_t$, $a_t$ 得到的值,跟输入 $s_{t+1}$, $\pi (s_{t+1})$ 得到的值中间,我们希望它差了一个 $r_t$, 这跟刚才讲的 TD 的概念是一样的。 但是实际上这样的一个输入并不好学习,因为假设这是一个回归问题,$\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)$ 是目标,你会发现目标是会动的。当然你要实现这样的训练,其实也没有问题,就是你在做反向传播的时候, $Q^{\pi}$ 的参数会被更新,你会把两个更新的结果加在一起。因为它们是同一个模型 $Q^{\pi}$, 所以两个更新的结果会加在一起。但这样会导致训练变得不太稳定,因为假设你把 $\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)$ 当作目标的话,你要去拟合的目标是一直在变的,这种一直在变的目标的训练是不太好训练的。 @@ -296,9 +296,9 @@ Q(s, a_3)=0 \end{array} $$ -但是假设你在状态 s,你采样过某一个动作 $a_{2}$ ,它得到的值是正的奖励。那 $Q(s, a_2)$ 就会比其他的动作都要好。在采取动作的时候, 就看说谁的 Q 值 最大就采取谁,所以之后你永远都只会采样到 $a_{2}$,其他的动作就再也不会被做了,所以就会有问题。就好像说你进去一个餐厅吃饭,其实你都很难选。你今天点了某一个东西以后,假说点了某一样东西, 比如说椒麻鸡,你觉得还可以。接下来你每次去就都会点椒麻鸡,再也不会点别的东西了,那你就不知道说别的东西是不是会比椒麻鸡好吃,这个是一样的问题。 +但是假设你在状态 s,你采样过某一个动作 $a_{2}$ ,它得到的值是正的奖励。那 $Q(s, a_2)$ 就会比其他的动作都要好。在采取动作的时候, 就看说谁的 Q 值最大就采取谁,所以之后你永远都只会采样到 $a_{2}$,其他的动作就再也不会被做了,所以就会有问题。就好像说你进去一个餐厅吃饭,其实你都很难选。你今天点了某一个东西以后,假说点了某一样东西, 比如说椒麻鸡,你觉得还可以。接下来你每次去就都会点椒麻鸡,再也不会点别的东西了,那你就不知道说别的东西是不是会比椒麻鸡好吃,这个是一样的问题。 -如果你没有好的探索的话, 你在训练的时候就会遇到这种问题。举个例子, 假设你用 DQN 来玩`slither.io`。 你会有一个蛇,它在环境里面就走来走去,吃到星星,它就加分。假设这个游戏一开始,它往上走,然后就吃到那个星星,它就得到分数,它就知道说往上走可以得到奖励。接下来它就再也不会采取往上走以外的动作了,所以接下来就会变成每次游戏一开始,它就往上冲,然后就死掉。所以需要有探索的机制,让机器知道说,虽然根据之前采样的结果,$a_2$ 好像是不错的,但你至少偶尔也试一下 $a_{1}$ 跟 $a_{3}$,说不定它们更好。 +如果你没有好的探索的话,你在训练的时候就会遇到这种问题。举个例子, 假设你用 DQN 来玩`slither.io`。 你会有一个蛇,它在环境里面就走来走去,吃到星星,它就加分。假设这个游戏一开始,它往上走,然后就吃到那个星星,它就得到分数,它就知道说往上走可以得到奖励。接下来它就再也不会采取往上走以外的动作了,所以接下来就会变成每次游戏一开始,它就往上冲,然后就死掉。所以需要有探索的机制,让机器知道说,虽然根据之前采样的结果,$a_2$ 好像是不错的,但你至少偶尔也试一下 $a_{1}$ 跟 $a_{3}$,说不定它们更好。 这个问题其实就是`探索-利用窘境(Exploration-Exploitation dilemma)`问题。 @@ -316,11 +316,11 @@ A: 因为 Q 值是有正有负的,所以可以它弄成一个概率,你先 **第三个 tip 是 `Experience Replay(经验回放)`。** Experience Replay 会构建一个 `Replay Buffer`,Replay Buffer 又被称为 `Replay Memory`。Replay Buffer 是说现在会有某一个策略$\pi$ 去跟环境做互动,然后它会去收集数据。我们会把所有的数据放到一个 buffer 里面,buffer 里面就存了很多数据。比如说 buffer 是 5 万,这样它里面可以存 5 万笔资料,每一笔资料就是记得说,我们之前在某一个状态 $s_t$,采取某一个动作 $a_t$,得到了奖励 $r_t$。然后跳到状态 $s_{t+1}$。那你用 $\pi$ 去跟环境互动很多次,把收集到的资料都放到这个 replay buffer 里面。 -这边要注意是 replay buffer 里面的经验可能是来自于不同的策略,你每次拿 $\pi$ 去跟环境互动的时候,你可能只互动 10000 次,然后接下来你就更新你的 $\pi$ 了。但是这个 buffer 里面可以放 5 万笔资料,所以 5 万笔资料可能是来自于不同的策略。Buffer 只有在它装满的时候,才会把旧的资料丢掉。所以这个 buffer 里面它其实装了很多不同的策略的经验。 +这边要注意是 replay buffer 里面的经验可能是来自于不同的策略,你每次拿 $\pi$ 去跟环境互动的时候,你可能只互动 10000 次,然后接下来就更新你的 $\pi$ 了。但是这个 buffer 里面可以放 5 万笔资料,所以 5 万笔资料可能是来自于不同的策略。Buffer 只有在它装满的时候,才会把旧的资料丢掉。所以这个 buffer 里面它其实装了很多不同的策略的经验。 ![](img/6.18.png ':size=550') -有了 buffer 以后,你是怎么训练 Q 的模型呢,怎么估 Q-function?你的做法是这样:你会迭代地去训练这个 Q-function,在每次迭代里面,你从这个 buffer 里面随机挑一个 batch 出来,就跟一般的网络训练一样,你从那个训练集里面,去挑一个 batch 出来。你去采样一个 batch 出来,里面有一把的经验,根据这把经验去更新你的 Q-function。就跟 TD learning 要有一个目标网络是一样的。你去采样一堆 batch,采样一个 batch 的数据,采样一堆经验,然后再去更新你的 Q-function。 +有了 buffer 以后,怎么训练 Q 的模型,怎么估 Q-function?你的做法是这样:迭代地去训练这个 Q-function,在每次迭代里面,从这个 buffer 里面随机挑一个 batch 出来,就跟一般的网络训练一样,从那个训练集里面,去挑一个 batch 出来。你去采样一个 batch 出来,里面有一把的经验,根据这把经验去更新你的 Q-function。就跟 TD learning 要有一个目标网络是一样的。你去采样一堆 batch,采样一个 batch 的数据,采样一堆经验,然后再去更新你的 Q-function。 当我们这么做的时候, 它变成了一个 `off-policy` 的做法。因为本来我们的 Q 是要观察 $\pi$ 的经验,但实际上 replay buffer 里面的这些经验不是通通来自于 $\pi$,有些是过去其他的 $\pi$ 所遗留下来的经验。因为你不会拿某一个 $\pi$ 就把整个 buffer 装满,然后拿去测 Q-function,这个 $\pi$ 只是采样一些数据塞到那个 buffer 里面去,然后接下来就让 Q 去训练。所以 Q 在采样的时候, 它会采样到过去的一些资料。 @@ -359,12 +359,20 @@ A: 整体来说,DQN 与 Q-learning 的目标价值以及价值的更新方式 * DQN 将 Q-learning 与深度学习结合,用深度网络来近似动作价值函数,而 Q-learning 则是采用表格存储; * DQN 采用了经验回放的训练方法,从历史数据中随机采样,而 Q-learning 直接采用下一个状态的数据进行学习。 +## 一些技巧 + +下面我们介绍下 DQN 的基本技巧: + +* 在 Atari 游戏里面,一般 mini-batch 设置为 32。 +* Experience replay 用在新问题上一般为 $10^6$。 + ## References * [Intro to Reinforcement Learning (强化学习纲要)](https://github.com/zhoubolei/introRL) * [神经网络与深度学习](https://nndl.github.io/) * [强化学习基础 David Silver 笔记](https://zhuanlan.zhihu.com/c_135909947) * [百面深度学习](https://book.douban.com/subject/35043939/) +* [机器学习(北理工)](https://www.icourse163.org/course/BIT-1449601164) * 苗光辉. 面向部分可观测环境的值迭代深度网络模型研究[D].北京理工大学,2018.