上一章我们讲到了可以用时域差分的学习方法,进行Q-Learning来求解最优的策略。
1) 假设我们进行了很多试验,每次的表达是 (s, a, r, s’, a’, r’, s’’, a’’, r’’, s’’’…)
2) 利用每一次transition的结果 (s, a, r, s’) 进行 Q 值更新,
存储 Q(s,a) 值的表虽然是随机初始化的,但是通过 agent 与 environment 的交互,反复迭代,最后会收敛,从而得到最优策略。
Exploration vs. Exploitation
这是强化学习中非常重要的一个概念。
强化学习希望能根据试验数据学习得到一个最优的策略 ,但是实际上在模型收敛之前我们并不知道什么策略才是最优的 。因此 ,我们需要在 exploration 和 exploitation 之间做一个权衡:一定情况下我们按照目前已知的 “最好” 的策略来执行action(exploitation),但是另外一些情况下,我们需要尝试新的选择,没准我们可以得到更好的结果(exploration)。
最简单的控制 exploration 的方法,就是设置一个随机概率,比如按 小概率随机选择 action,大概率情况下按照目前的policy 来执行 action 。
这种简单粗暴的方式的问题是,当模型都快收敛了,他仍然是在每个状态按概率随机选择action,所以一个改进的办法是随着迭代次数的增加,也慢慢变小。但是有一个更好的解决方案,就是把 exploration 合并在求解策略的过程中一起来表达。
1) 定义一个函数u是一个值(比如Q值或者状态值),n是到达该状态的次数,k是一个奖励系数。
2) 把Q-Learning里面的Q值更新步骤更新为:
由于Q值的计算是需要考虑后续若干 time step 的影响的,在n很小的时候,Q 值由于计算的不够科学,那么依靠k/n,仍然有一定概率会选择执行某个 action 进行尝试;当路径尝试的比较充分后,k/n会非常的小,前面的Q 值占主要的影响成分。
状态空间的泛化
最基本的Q-Learning我们可以看到,需要保存一个(s,a)大小的 Q 值表格,用于记录所有的 Q 值。
但是现实生活中,状态可能是极其海量甚至是无限的,我们不可能把他们全部遍历,也没有那么大的空间把这么大的Q值表装内存里面。所以我们需要像机器学习模型开发特征一样,对状态进行一些泛化,比如:用一些特征来描述当前状态,这样类似状态都是可描述的;同时,对于 Q-Learning 所需要的数据量也会大大减少。
上图这个例子足以说明问题:他们是三种不同的状态,尤其是第三个图和第一个图,右上角少了一个白点。如果按照严格定义,他们必须是三种不同的state,然后结果是我们会先崩溃。所以必须用一些特征来描述他们,使得类似状态具有泛化能力。
状态的特征表达及模型训练
如果我们有机器学习的相关基础,这里就很好说了。简单几句话就是做一些手绘特征来描述当前的状态,比如上面的图:离你最近的豆子的距离,离你最近的 ghost 的距离,当前全局有多少 ghost 等等。
在特征表达的基础上,假设状态的值和状态的描述是紧密相关的(确实也是这样的),那么我们可以把状态的特征和状态值建立一组映射,简单一点,采用线性关系:
把它和Q-Learning结合在一起,通过Q-Learning迭代过程中产生的误差就可以对feature的权重进行梯度更新了。
过程如下:
1) 实验得到 transition(s, a, r, s’)
2) 定义
3) 对Q(s,a)和w进行更新:
上述过程可以用类似线性回归的方式来辅助理解,但是并不能完全等同。
对于线性回归,使用最小二乘计算误差可以得到误差为:
对w求偏导有:
SGD进行更新:
事实上,扩号中间的误差,近似的可以解释为上面Q值迭代的 difference 。
既然说到了如何手绘特征,那么肯定也会有特征过拟合的问题,这里就不细讲了,了解机器学习的人都有基础。
Deep Q Network
上述描述state的方法显然是与应用场景捆绑的非常死的,因为feature是手工定制的,那么对于一类问题就无法用一种模型来解决。比如玩Atari视频小游戏,每种游戏的 state 如何描述都需要手工定制特征。所以就有了deeplearning和 Q-learning 结合的思路,用 deeplearning 来拟合 Q(s,a) values,用 Q-learning的方法来计算target并得到需要回传的误差,从而训练深度神经网络,得到更好的 Q(s,a) 模型。鉴于融入了网络参数,现在对Q的表示,写为。
如果用深度神经网络来拟合Q值函数,有如下两种做法:a)把action的值作为网络的输入,与 state 一起直接建模;b)使用同样的输入和参数,在输出层把各个 action 分开,分别计算他们的 Q Value。
上面写的那个线性拟合的 Q 值函数表达,可以看做是第一种形式。现在推荐采用第二种方式,因为学习的时候,只需要一次前向计算,就可以得到所有action枚举值对应的 Q Value,也能一次性得到最大的那个,正是我们进行强化学习想要的。
按照 DeepMind 的论文描述的方案,他们玩 Atari 视频小游戏的强化学习模型是这样的:输入层使用最近的4帧画面,分别转换成84*84的灰度图,把他们作为含4个 channel 的图像输入 CNN,经过三个卷积层和两个全连接层(具体参数见论文)后,对于最后一层的每个神经元使用线性激活函数进行输出。由于 Atari 游戏一共是18个可选的 action,因此整个网络最后一层的输出节点数是18,每个节点的输出值,都认为是在当前 state选择对应 action 时候的 Q Value。
现在问题回到了对Q Value的线性回归拟合问题,可以直接使用最小二乘的方法来进行最优化求解:
具体步骤如下:
1. 给定输入后进行一次前向计算,得到所有可用action的QValues输出;
2. 选定一个action a执行后,这个时候会来到新的state s’,并且得到一个reward r。重复步骤 1,对s’计算一次Q Values,并选择输出最大的那个;
3. 根据步骤 2 的结果计算 action a应该拟合的目标是,对于 a 以外的那些输出节点,把他们应该拟合的 target 设置成步骤 1 里面的输出值,这样他们得到的误差是0;
4. 通过 BP 算法对整个 CNN 网络进行更新。
Experience Replay
虽然现在可以通过深度神经网络来拟合 Q 值函数了,但是人们发现这种非线性的拟合并不是特别稳定。事实上早先提出可以进行特征泛化的时候肯定也有人试过神经网络,但是 DeepMind 为啥就能做出效果呢?
他们用了一个很重要的技巧叫做 experience replay。具体做法是把大量尝试路劲上的都用一个容器存起来,叫做 replay memory。在训练整个 Q 值网络的时候,我们主要是要训练 的表达,而不限于是在哪个time step,所以干脆每个 mini-batch 直接从 replaymemory里面随机采样一批的样例出来进行训练。之所以这样做,而不是攒一系列邻近 time step 的样例来进行BP,是因为这种随机采样的没有依赖关系的样例可以消除样例之间的相似性,避免训练过程落入局部最优。而且这种训练方法,也和现实世界更加接近,试想旁观别人玩游戏,我们也都是在记各种场景的处理策略,而非记忆一段连续的游戏样本。
引入 experience replay后,还考虑 exploration-exploitation,最后的训练过程如下:
1. 根据初始化的网络,结合state s,以 的概率随机选择一个 action,否则选择 Q 值最大的那个 action 输出;
2. 选定一个 action a 执行后,这个时候会来到新的 state s’,并且得到一个 reward r。把存入 replay memory D;
3. 从D中随机采样出一批样例送入 DQN,每个样例计算两个 Q 值:
和每个样例输出最大的那个 ;
4. 使用作为误差训练整个 DQN 模型。
延伸内容
目前我们讨论了离散状态的 MDP ,也讲到了非离散状态的状态描述,但是 action 空间仍然是离散的。如何描述连续的 action 空间,比如对话模型中机器人根据上下文描述的对话状态,选择如何回答(执行哪个操作)的策略描述,不是那么容易用离散空间来描述的。相关内容还需要进一步补充。