## 强化学习解析与实践 文/吴岸城 >听到强化学习,大多数读者第一反应是 AlphaGo,这一反应既对也不对。AlphaGo 刚出来的时候确实震撼了一大批人,但强化学习这个概念其实在 AlphaGo 之前就早已出现。下面就让我们一起来深入了解强化学习。 ### 吃豆子和强化学习 要了解强化学习,就要从生物界找灵感,数据科学的大部分范畴都应该归结为实验科学和“空想”仿生学,我们可以从最低等的生物——一个单细胞生物开始,看看单细胞生物是如何学习的。首先给单细胞生物设计一个场景,它只有上下左右四个方向可以移动;周围有微生物,单细胞生物可以吃,看能吃多少;但还有些病毒,如果单细胞生物误食了就直接挂掉,然后系统会再产生一个新的单细胞生物继续上面的循环,当然系统在 reset 这个单细胞生物时,已将之前遇到微生物(食物)和病毒(天敌)的经验输入到新的单细胞生物上。 从单细胞生物这种求生避险的本能,我们可以抽象出强化学习的以下几个概念。 1. 环境(environment)也就是边界或者说移动范围,还有一些规则,比如规定吃到东西单细胞生物就可以长大,吃到病毒就挂掉重新开始。 2. 奖励(rewards):这里的奖励有两个,一个是吃到微生物就可以成长,我们定义该奖励是正值;另一个是吃到病毒就减分或挂掉,我们定义该奖励为负值。 3. 动作(actions):也就是允许的单细胞生物的动作。 好,整个过程其实和吃豆子这个游戏很像,所以我们就以吃豆子为例(如图1所示)。 图1  吃豆子游戏 图1 吃豆子游戏 这里有四处游荡的怪物,也有吃豆人(也就是我们的主角,吃了会加分的豆子)。而除此之外游戏的路径和图形就是环境。 我们按照之前单细胞生物的知识点再来梳理下。 1. 状态(states),有的书上也称为 observation、environment。状态指的就是环境(environment)的状态,即在当前的情况下,每一次移动后,各个怪物的位置,以及豆子和整体环境的变化,一般情况下是游戏中任意时刻整个画面的一帧,将它作为输入状态(states); 2. 动作(actions),每个状态下,吃豆人什么样的动作; 3. 奖励(rewards),每个状态时下,在动作(action)之后带来的正面或负面反馈,比如加分或扣分; 4. 智能体(agent),这里指的是吃豆人。 将单细胞生物或者吃豆人这类最简单的和环境有交互的状态、动作等抽象出来后,我们希望继续深入了解单细胞生物或者吃豆人是如何从环境中学习到趋利避害的“本领”的,请继续往下看。 ### 马尔科夫决策过程 吃豆人的游戏中,每一步动作后环境的状态会发生变化:可能吃了一个豆子,或者是往前走一步,或者被杀死,同时会带来正向奖励或负向奖励(负向奖励就是惩罚),沿着目前的这步变化,可以推导出后期的奖励。 换句话说,每一次动作后,都会对未来产生一个可能的路径,而我们的目标是在所有的路径中寻找最优的解。 举个例子,我们从上海乘车到北京,选择了最便宜的路线,此路线经过10个车站,第二站是南京: 上海→南京→……→北京 但如果除去始发点上海站,那么由第二站南京到最后的北京站: 南京→……→北京 这路线仍然是余下9个站之间最便宜的。 上海→南京的选择可以看成 action,选择了南京后,因为途径了9个站,我们理论上得到了多条路径,选择后发现还是原有的路径也就是上海→南京→北京这段路中间的南京→北京这段是最便宜的。接下来,我们再选择南京下一站徐州……这个过程一直重复下去,直至到达北京为止。 以上寻找最优路径的过程就是一个 MDP 过程(Markov decision process,MDP,马尔科夫决策过程),MDP 是在 MP(马尔科夫过程)上的一种优化,增加了一个关键元素:动作集,也就是前文提到的 actions(如图2所示)。 图2  马尔科夫决策过程示意图 图2 马尔科夫决策过程示意图 我们用图论来表示 MDP 的一个过程,MDP 过程表示为图中的状态转移,包括五个主要概念: 1. 状态(state,S):图中浅色的圆圈所示,为环境的“观测值”。 2. 动作集(actions set):图中深色的圆圈所示,在图中的状态转移过程中,动作集为{a0, a1}。动作就是 MDP 比 MP 增加的部分。 3. 状态转移概率(Psa):指定在状态 s 的情况下执行动作 a 后的状态转移概率。如在一个状态 s0 下执行一个动作 a0 后,将会有0.5的概率转移回 s0,0.5的概率转移到 s2,但是我们有可能不知道状态的转移概率,即只有在观察到状态转移之后才知道下一个状态是什么。 4. 奖励函数(reward):作为强化学习中最重要的概念,奖励函数是与每个状态对应的,在智能体执行某个动作以后,环境过渡到下一个状态时给智能体的反馈,可以是正的或者负的,如图中浅色箭头所示,由于要求智能体执行某个动作后才能看到结果,所以称强化学习具有时间延时(time delay)性。假如我们在训练一条狗,当它做出正确的事情时,我们会说“乖狗狗”并给它吃的,而做错了一件事时,叫它“坏狗狗”,没有吃的,久而久之小狗就会知道怎样才是正确的做法。与此相同,正确地选择奖励函数,能够提高智能体的训练效果和训练速度。 5. 折扣因子(discount factor,gamma):是对未来奖励的不确定性的表示,状态转移的过程具有一定的随机性,时间间隔越久,未来的不确定性越强,未来能够获得奖励的可能性也就越小。所以选择一个[0,1]的一个值作为折扣因子,时间越是向后推迟,我们对未来的预测就要乘上更多的折扣因子。 说到这里,很多读者可能会想,这和最优路径选择好像差不多?这里有个误区,尤其是对于 AlphaGo 或者其他的游戏,强化学习和最优路径选择的区别是,强化学习过程不能够穷尽所有的路径,因为根本看不到最终的状态。比如,下象棋时我们可以穷尽所有的路径,因为象棋的棋盘相对较小。而对于围棋来说,我们没有可能计算完所有的情况,能算十步已经很了不起了,对机器来说一些简单的问题可以遍历,但围棋这样的要遍历一遍再找出最优路径是不可能的,所以强化学习不是找最优的,而是找对于目前状态来说可能是最优的,在这一过程中并没有模拟未来情况(这点也和最优路径有区别),而是直接计算出未来可能的分值。 说完了 MDP 的解释,再了解其基本公式,更深入地理解它是如何实现的。 公式1:假设我们在描述这样一个转移状态,从s0到sn,公式1描述了一条路径。 公式2:我们的目标是使获得的总价值最大,总价值表示为公式2,即从 s0 开始到一个 episode 结束获得的总价值,或者表述为未来的累计奖励值;R 表示当前状态下获得的奖励值。其中的 gamma 就 是折扣因子,因为在状态转移的过程中未来的状态是随机的,也就是我们不知道未来会发生什么,所以对于未来的奖励乘上折扣因子,并且是随着时间呈指数增长。 公式3:若用 π 表示一系列动作所组成的策略(policy)的话,那么总共获得价值就可以用一个价值函数 Vπ(s) 来表示,即为在状态为 s=s0,策略为π的条件下,价值的期望值(因为状态转移的过程具有随机性,所以这里的价值用期望来表示)。 公式4:对上式做简单的变形(将 gamma 提出来),若该式表示 s0 开始到一个 episode 结束时的总价值,那么括号里面表示的就是从 s1 开始到一个 episode 结束时的总价值,整理一下变为公式5。 公式5:Vπ(s) 表示状态 s 处对未来总价值的预测,后面的 Vπ(s') 表示状态 s' 处对未来总价值的预测,因为下一时刻的状态由 action 和转移概率决定,所以有了这个公式,这个公式被称为“贝尔曼等式”,是处理 MDP 优化的重要概念。 公式6:而求解贝尔曼等式就相当于使函数最大化的过程,我们用 V* (s) 表示通过选择适当的策略获得最大的价值,这个过程可以从两个角度来考虑,值迭代(value iteration)和策略迭代(policy iteration)。 最后我们要感谢马尔科夫让我们在状态之间能游刃有余地进行切换:从状态 s 到状态 s' 我们不需要关心其他状态,只需要关心上一个状态即可,自然也就有了状态转移概率 P(s'|s) 一说。 ### 理解 Q 网络 我们花了很多篇幅谈到马尔科夫决策过程和它的求解目标,那么这一切和强化学习又有什么关系呢? 从上面对 MDP 的了解来看,MDP 求解其实是一个估值过程,而这类的估值问题是强化学习里的一个关键目标:即每个状态之后都要选择一个动作,每个动作之后的状态也不一样,我们需要一个值来评估某个状态下不同动作的得分。如果知道这个得分,我们也就能选择一个使得分最优的动作来执行。这就是强化学习中的关键一步动作估值(Action-Value functionQπ (s,a))了,可以简单写作 Q(s,a),按照以上思路继而求最优动作估值(Q* (s,a)),这个 Q* 我们可以认为是最理想的值,只能无限逼近。为了达到最优的估值 Q*,需要不停地迭代,也就是每次根据新得到的 reward 和原来的 Q(s',a') 值来更新现在的 Q 值。我们来看看图3的结构图,这里的DQN指的是深度 Q 网络(Deep Q-Network),大白话就是用和环境的交互来衡量或评价动作(action)的好坏。 图3所示为 DQN 算法的网络示意图,中间的 Network 表示一个神经网络,输入为当前的状态,输出为对应不同的 action 的 Q 值(未来的总价值)。 这里给出 Q 版的贝尔曼等式,在训练 q-network 时,我们把等式右侧的值作为目标(target),使左侧的预测值能够接近这个目标。之所以这样选择是因为右侧比左侧多了一个 s 状态下所获得的奖励(reward)的信息,可以理解为右边比左边更有可信度。 图3  DQN网络示意图 图3 DQN 网络示意图 Q 的学习过程: ``` def learnQ(self, state, action, reward, value): oldv = self.q.get((state, action), None) if oldv is None: self.q[(state, action)] = reward else: self.q[(state, action)] = oldv + self.alpha * (value - oldv) ``` 请看最后一句,描述了旧有状态和目前输入状态下如何产生一个新的 Q 值。 以上,我们深入理解了马尔科夫决策过程以及 Q 学习过程,这也是 DQN 网络的核心内容。现在要考虑实现一个 DQN 网络该怎么做?请看下节。 ### 模拟物理世界:OpenAI 2016年4月28日,OpenAI 对外发布了人工智能一款用于研发和比较强化学习算法的工具包 OpenAI Gym,正如 Gym 这词所指的意思(健身房)一样,在这一平台上,开发者首先有一个可以模拟物理世界的接口(要想真正模拟还需要接入相关环境,OpenAI 只提供接口),我们可以模拟各种物理环境,比如飞船飞离地球,太空失重,3D 世界,或者简单到一个2D 游戏场景,比如吃豆子,另外开发者也可以把自己开发的 AI 算法拿出来训练和展示。 综上,OpenAI 是为强化学习创造一个虚拟的世界,这个世界模拟了现实生活的各种物理规律,或者就称为规律,在这里我们的智能体才能很好地完成交互,进而完成强化学习的过程。 OpenAI Gym 最重要的功能就是提供各种强化学习环境。下面代码中的这句话 env=gym.make('CartPole-v0') 是实例化一个 CartPole 环境。后面几句代码是在更新动画,并且在得到 action 后做一步环境的变化。 ``` importgym env = gym.make('CartPole-v0') #实例化一个 CartPole 环境 fori_episode in range(20): observation = env.reset() fort in range(100): env.render() #更新动画 action = env.action_space.sample() observation, reward, done, info = env.step(action) #推进一步 ifdone: break ``` 其中最关键的是 action = env.action_space.sample(),Gym 里面直接用了一个随机采样,并没有实现 DQN 网络但预留了接口,作为 action 输出以及接受 reward 和 state 的反馈。 observation, reward, done, info = env.step(action) 这一部分里每执行一步 action 都将有4个参数的反馈,这4个参数是根据每个游戏的游戏规则来反馈的。这里看出 Gym 确实是模拟了游戏的环境。 CartPole 环境要求平衡一辆车上的一根棍子,如图4的第一个环境表示。该图是 OpenAI Gym 提供的部分自动控制方面的环境。除此之外 OpenAI Gym 还提供了 3D 游戏、物理世界模拟、文本和游戏方面的环境,具体可以查看官方说明。 图4  CartPole游戏演示图 图4 CartPole 游戏演示图 前文提到强化学习环境其实是马尔科夫决策过程,马尔科夫决策过程的四个基本元素分别是状态、动作、转移概率和奖励函数。对应之前提到的马尔科夫概念,我们做一个状态模拟,说说在 OpenAI 中如何实现表示马尔科夫决策过程的四个基本元素。 - 状态:代码中的 observation 就是马尔科夫决策过程的状态。更正确地说是状态的特征。CartPole-v0 的状态特征是一维数组,比如 array([-0.01377819, -0.01291427, 0.02268009, -0.0380999 ])。有些环境提供的状态特征是二维数组,比如 AirRaid-ram-v0 环境提供的是二维数组表示的游戏画面。 observation = env.reset() 是初始化环境,设置一个随机或者固定的初始状态。env.step(a1) 是环境接受动作 a1,返回的第一个结果是接受动作 a1 之后的状态特征。 - 动作:代码中的 action 就是马尔科夫决策过程中的动作。CartPole-v0 的动作是离散型特征。在 OpenAI Gym 中,离散型动作是用从0开始的整数集合表示,比如 CartPole-v0 的动作有0和1。另一种动作是连续型,用实数表示。 - 奖励函数:在 OpenAI Gym 中,它提供给强化学习一个环境。step 函数就是你的手柄,在手柄上按键相当于传入的值。 代码中的 reward 就是马尔科夫决策过程中的奖励,用实数表示。在 OpenAI Gym 中,奖励函数也没有显式地表示出来,也是通过 env.step(a1) 的结果表示。env.step(a1) 返回的 reward 满足奖励函数。 - 转移概率:指的是玩游戏时当前画面执行了一个操作后,所呈现下一帧(下一帧有无穷种可能)画面的可能性,在 OpenAI 中无法显式地观测到转移概率。 最后值得一提的是,env.step 返回的第四个结果 info 是系统信息,给开发人员调试用,不允许学习过程使用。 这里只介绍在 OpenAI Gym 上实现 Q Learning 算法需要的知识。想了解更多 OpenAI Gym 知识,可以参考 OpenAI Gym 的官方文档。 ### 实现一个DQN #### DQN 代码实现 学习了 OpenAI 的使用后,现在开始着手实验 DQN 代码。 DQN 代码的安装和训练非常简单,它是依赖 OpenAIGym的,所以首先必须装一个 Gym,请参见下面这行安装脚本: ``` $ pip install tqdm gym[all] ``` 接着为 Breakout 这个游戏训练一个模型: ``` $ python main.py --env_name=Breakout-v0 --is_train=True $ python main.py --env_name=Breakout-v0 --is_train=True --display=True ``` 接下来可以测试和记录游戏的状态: ``` $ python main.py --is_train=False $ python main.py --is_train=False --display=True ``` 前文在提到 OpenAI 时,讲到了 OpenAI 预留接口,并没有实现 DQN。为了更深入地理解 DQN 的结构,我们了解下 DQN 的代码实现,先从 main 函数入手,追踪下 Agent 函数。 ``` def main(_): gpu_options = tf.GPUOptions( per_process_gpu_memory_fraction=calc_gpu_fraction(FLAGS.gpu_fraction)) withtf.Session(config=tf.ConfigProto(log_device_placement=True, gpu_options=gpu_options)) as sess: # with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess: config = get_config(FLAGS) or FLAGS ifconfig.env_type == 'simple': env = SimpleGymEnvironment(config) else: env = GymEnvironment(config) if not FLAGS.use_gpu: config.cnn_format = 'NHWC' agent = Agent(config, env, sess) ifFLAGS.is_train: agent.train() else: agent.play() if__name__ == '__main__': tf.app.run() ``` 关键的一句在这里:agent = Agent(config, env, sess),这是 agent 处理动作和状态的主要函数,这句话将往 Agent 函数里传送 config(配置文件),env(环境),sess(TF 的对象)。 接下去看看 Agent.py 里有哪些关键点?在 agent 文件的 play 函数中,我们找到了以下几行如何处理动作和状态的关键点: ``` # 1.predict action = self.predict(self.history.get()) # 2.act screen, reward, terminal = self.env.act(action, is_training=True) # 3.observe self.observe(screen, reward, action, terminal) ``` 这些关键点的含义如下。 第一步用历史数据预测下一个 action。 第二步把预测出来的这个 action 放入环境中,得到下一个 reward。 第三步在新的 action、reward 基础下,继续‘看’整体的状态(state)。 在 train 函数中,同样能找到它们。 ``` # 1.predict action = self.predict(self.history.get()) # 2.act screen, reward, terminal = self.env.act(action, is_training=True) # 3.observe self.observe(screen, reward, action, terminal) ``` 除此之外,还有以下和 play 函数不一样的地方。 ``` ifterminal: screen, reward, action, terminal = self.env.new_random_game() num_game += 1 ep_rewards.append(ep_reward) # 存储每个 episode 的累积 reward ep_reward = 0. else: ep_reward += reward actions.append(action) total_reward += reward # 每 self.learn_start 次统计训练结果,并在适当时候保存模型 ifself.step >= self.learn_start: ifself.step % self.test_step == self.test_step - 1: avg_reward = total_reward / self.test_step # 平均每个 step 的 reward avg_loss = self.total_loss / self.update_count # 每次参数更新的平均 loss avg_q = self.total_q / self.update_count # 每次参数更新的平均 q 值 try: max_ep_reward = np.max(ep_rewards) # 曾经到达的最高的得分 min_ep_reward = np.min(ep_rewards) # 曾经到达的最低的得分 avg_ep_reward = np.mean(ep_rewards) # 平均得分 ``` 以上就是 Agent 的运作方式,接着我们回到 DQN 函数中的 `def build_dqn(self)`,发现函数主要是构建 dqn graph 结构,包括了 train-network、target-network、`pred_to_target`、optimizer、summary。 其中 train-network、target-network 都是差不多的卷积神经网络,用于对 state 的观测。 在 config.py 中主要是一些配置信息,以下是 M1 配置信息,环境的类型设置为‘detail’ action_repeat=1。 ``` class M1(DQNConfig): """ 某种训练方式的配置,其中: AgentConfig 为 DQN 的配置 EnvironmentConfig 为 gym environment 的配置 """ backend = 'tf' env_type = 'detail' action_repeat = 1 ``` 结合论文我们试着修改一些参数,得到 M4 这个配置。 ``` class M4(DQNConfig): backend = 'tf' env_type = 'simple' action_repeat = 4 ``` 以上 M4 配置环境的类型设置为‘simple’,而 action_repeat 设置为4,表示每一 action 在训练内重复4次,同时让 reward 持续累加,个人认为这样能够起到加快训练的目的。 我们用 M1 和 M4 的配置跑出的模型分别去玩 BreakOut 游戏。用 M1 配置训练了 BreakOut 游戏2000万次,得到模型后,再用这个模型去玩游戏,游戏在玩到只剩一个人的时候,得到32分,而这时 DQN 网络预测的最高得分是55分(如图5所示)。 图5  M1模型打砖块breakout游戏演示图 图5 M1 模型打砖块 breakout 游戏演示图 再来看 M4 模型,在训练游戏1600万次之后、M4 模型操作将游戏玩到只剩3个人时,已经得到35分,而 DQN 网络预测的最高得分是209(如图6所示)。 图6   M4模型打砖块breakout游戏演示图 图6 M4 模型打砖块 breakout 游戏演示图 从这个过程中,我们能明显看出 M4 的参数优化得比 M1 要好,但有读者要问了,如果我还想观察中间过程怎么办?我甚至想看每一个 reward,还有模型训练中的准确率和最终得分,等等,这该怎么办?有没有更好的方法能够将整个训练过程图表化出来呢?那下面就要请 TensorBoard 出场了。 #### DQN过程的图表化 TensorBoard 是 TensorFlow 中的可视化工具,TensorFlow 的版本还在不停地迭代,所以 TensorBoard 的具体使用步骤请直接参考官方网站。这里只尝试用 TensorBoard 将训练过程中的对应日志生成相应图表,为了观察对比,我们将一些关键指标罗列出来。 - 在所有的标量图(单值的变化)中横轴表示训练的 step 数,纵轴表示每个量的数值,反映出在训练过程中我们关注的每个量的变化情况。 图7  标量变化曲线 图7 标量变化曲线 图7为 m1 模型的结果中的标量变化曲线,图中各参数含义如下: average.reward:平均每个 step 的 reward。 average.loss:每次参数更新的平均 loss。 average.q:每次参数更新的平均 q 值。 episode.max reward:曾经到达的最高得分。 episode.min reward:曾经到达的最低得分。 episode.avg reward:平均得分。 episode.num of game:游戏名字,如:breakout。 training.learning_rate:学习率。 - 在所有的矢量图(多值的变化)中:黄颜色(左侧)代表 M1 模型的结果,绿颜色(右侧)代表 M2 模型的结果。 图8  M4模型标量变化曲线 图8 M4 模型标量变化曲线 TensorBoard 的矢量图包括三个维度,右侧的坐标为 step 数(即表示时间),下侧的坐标表示 Tensor 中的索引,每一个横轴上的图形表示在当前时刻(step)不同的值上面的概率分布(如图9所示)。 图9  episode rewards M1、M2对比 图9 episode rewards M1、M2 对比 episode rewards:存储每个 episode 的累积 reward,左侧图表现更好。 episode actions:每次迭代中选择的 action 的分布,如 breakout 游戏中有6个 actions,无评价意义(如图10、图11、图12所示)。 图10  episode actions M1、M2结果对比 图10 episode actions M1、M2 结果对比 图11  第6个action的q值变化M1、M2结果对比 图11 第6个 action 的 q 值变化 M1、M2 结果对比 图12  第0个action的q值变化M1、M2结果对比 图12 第0个 action 的 q 值变化 M1、M2 结果对比 DQN 训练过程用图表展现出来能更好地观察其中变化的情况,希望大家善用此工具。 此前,我们分析了 DQN 的代码,尝试着调参,得到了一个更好的 M4 模型,又学习了用 TensorBoard 图表化展示强化学习的整个过程。在实践的过程中又多了很多对于强化学习的总结和思考,我们也一起来总结下。 ### 关于强化学习的思考 #### 强化学习的特殊性 强化学习的概念很早就有,这里所说的强化学习专指深度强化学习,这是在深度网络发展起来后,重新利用强化学习的机制而发明的算法。 强化学习当然不能解决所有的问题,但我们要了解强化学习究竟能够解决哪一类的问题。通常来说,强化学习适合那些能够随着环境的改变而强化自己的智能体——Agent。例如,机器人在移动时适应房间,在各种游戏领域甚至各种对抗比赛中也都可以应用强化学习;对于棋类的比赛,大家比较熟悉了,AlphaGo 就是使用强化学习的方法达到并超过人类水平的。在这些领域中 Agent 随着环境的变化,选择合适的动作,并且能在这种环境的变化和动作的改变中得到反馈,这样的反馈(奖励或惩罚),将使 Agent 一步步地提高适应性,并且在某单一任务或者多项任务中得到最高分。 我们来稍稍回忆一下前文提到的强化学习的概念。在训练 Agent 玩吃豆子游戏时,“环境”可以在这一局游戏结束并且胜利时给出一个正回报,而在游戏失败时给出一个负回报,其他的情况呢?给出一个零回报,Agent 的任务就是从这个非直接有延迟的回报中学习,目标是使回报最大化。 强化学习,从它出生开始就常常和有监督学习这类的函数逼近问题放在一起讨论,强化学习并不是完全的有监督学习,它们之间有几个重要的不同点。 1. 训练数据的获取方式:强化学习的任务是学习一个新的目标函数,在一般的有监督学习上,我们可以看到训练集是 (x,y),在这种模式下,(x,y) 一开始就是已知的,而在强化学习中不一样。强化学习中对应的 (x,y) 实际上是,其中 s 是状态,而 π(s)是在这种状态下的最优化动作。强化学习中训练信息是从跟环境中互动而得到的值。而环境也不是一成不变的,Agent 新一轮的动作,又对环境产生影响。 2. 探索:在强化学习中,Agent 通过其选择的动作序列影响训练样例的分别。这产生了一个问题:哪种实验策略可产生最有效的学习?学习器面临的是一个权衡过程,是选择探索未知的状态和动作(收集新信息),还是选择利用它已经学习过的、会产生高回报的状态和动作(加强神经元之间的联系)。 3. 目标不同:强化学习的数据是序列的、交互的、并且还有反馈的(reward)。这就导致了它与监督学习在优化目标的表现形式的根本差异:强化学习本质可以算作是一个决策模型,监督学习更偏向于在固定数据中寻找答案。强化学习是 Agent 自己去学习,监督学习是跟着设计者给出的既定方向在收敛。 4. 长期学习:不像一般的函数逼近任务,类似一个机器人学习问题,经常要求此机器人在相同的环境下使用相同的传感器学习多个相关任务。怎样捡起一个球以及怎样从打印机中取得打印纸等。这就要求算法使用先前获得的经验或知识在学习新任务时减小样本复杂度,并且整个过程是在不停迭代的。 5. 强化学习是有“生命”的:你可能也不知道你训练出来的模型到底能做到什么“程度”,它的收敛并不是按照我们事先给出的先验数据收敛,而是根据整个外部环境的反馈数据进行收敛,而外部环境又是在不停变化中的,这点非常像动物或人的学习方式;加上神经网络的不可解释性,往往最后能达到出乎意料的效果,可以说强化是有“生命”的,或者说是有自我进化能力的。 #### 知识的形成要素:记忆 在强化学习中要找到终身学习的开启大门,或者说要将这种“有生命”的状态延续下去,就有必要去模拟人的学习路径。人是在环境中获取知识的一种动物,在环境中被教育,被奖励,被惩罚,非常像前文模拟的强化学习环境,而有了基础的“神经反射”后,人类会一步一步强化这种反射,进而形成经验,再从经验形成知识,最后一代代地传递下来。而这都要归功于我们一直习以为常的大脑功能:记忆。所以这部分我们先不谈强化学习,而是来看看记忆网络的发展。 提到具备记忆的网络我们的第一反应基本都是 LSTM。它巧妙地利用了几个门(gate)实现了对是否记忆的控制。我们认为这种模式实际上是不完全的知识存储,因为 LSTM 只会对一个序列(sequence)里的目标进行记忆,而且严格地一次只输出一个字符或一个词(如图13所示)。 图13  长短时模型(Long Short Term Model,LSTM)通过隐性的共享记忆结构,不完全地实现知识的存储。 图13 长短时模型(Long Short Term Model,LSTM)通过隐性的共享记忆结构,不完全地实现知识的存储。 LSTM 的出现起码解决了神经网络能否记忆的问题,虽然解决得还不够好。图14中的这位就是专门为了解决记忆问题而产生的神经图灵机(Neural Turing Machines,NTM)。 图14  神经图灵机NTM 图14 神经图灵机 NTM 2014年 DeepMind 的同学们提出一种结构:神经图灵机,大家都知道图灵机是对外部环境的刺激做出的一种反馈(想想强化学习),而神经图灵机参考了这种反馈。 神经图灵机(NTM)架构包含两个基本组件:神经网络控制器和存储器组。图14提供了 NTM 架构图。像大多数神经网络一样,控制器通过输入和输出向量与外部世界交互。与标准网络不同,它还使用选择性读写操作与存储器矩阵(Memory)交互。类似于图灵机,我们将参数化这些操作的网络输出称为“Heads”(包含读写)。 这个结构可以让 NTM 在只接受少量的新任务观测情况下或者说在外部的刺激下实现快速学习记忆。而这个简单的结构,据说是模拟大脑皮质的记忆功能。 接着来看看 NTM 寻址问题(如图15所示),关键向量 kt,关键的强度 βt 被用来在存储举证 Mt 里做基于内容的寻址。根据 γt 权重将会调整并用在记忆的访问上。 图15  寻址机制的流程图 图15 寻址机制的流程图 存储记忆的模块确定了、寻址机制确定了,但是如何往里进行读或者写呢?首先要让读写具有可区分性,以便让神经网络学习读取和写入的位置。这比较麻烦,因为内存地址是完全离散的。NTM 采取一个非常聪明的解决方案:每一步都进行读写(如图16所示),只是在不同的范围内进行,图17描述了读取写入的具体流程,其中图17的左边为读取,右边为写入。 图16  每一步都有读写(参考自http://distill.pub/2016/augmented-rnns/。) 图16 每一步都有读写(参考自 http://distill.pub/2016/augmented-rnns/。) 图17  读写机制 图17 读写机制 以上我们谈到 NTM 这种记忆网络,下面我们来看看另一种记忆网络——记忆的进阶 MANN(MANN Memory-Augmented Neural Networks)。 MANN 论文的摘要这样写道:“尽管最近在深层神经网络的应用方面取得了突破,但是一个持续挑战是“一次性学习”。传统的基于梯度的网络需要大量的数据来学习,常通过广泛的迭代训练。当遇到新数据时,模型必须无效地重新学习它们的参数,以充分地将新的训练集信息合入模型。而具有增强记忆结构的算法,诸如神经图灵机(NTM),能提供快速编码和检索新信息的能力,因此可部分地消除常规模型的缺点。在这里,我们演示了记忆增强神经网络快速吸收新数据的能力,并利用这些数据,准确地预测出几个样本。我们还引入了一种用于访问专注于存储器内容的外部存储器的新方法,与之前使用基于存储器基于位置的聚焦机制的方法有所不同。” 这样看来 MANN 的论文基本上就是针对 NTM 做的一些“变化”,这里不好说一定是改进,笔者的理解是应用范围不同。 请看图18右侧图,第一次训练完数据后,会使用一个外部存储器来记忆绑定的样本,该样本是一个类别的标签信息,第二次如果有一个样本被送入模型,可以从外部存储器中检索这个绑定信息以进行预测。具体来说,就是将特定时间步长的样本数据xt绑定到合适的类别标签 yt 上。而对于这种绑定策略,利用了反向传播的误差信号,用该信号对时间较早的权重更新调整,也就是更新了绑定策略。 图18   MANN读写机制 图18 MANN 读写机制 以上的这种信息被传递进模型,被整理计算后决定是存储下来还是丢掉,这种机制(任何让我们有选择地把信息从模型的一个地方引导到另一个地方的机制)可以被认为是一种注意力机制。分类模型里的属于“读”注意力,生成模型里的属于“写”注意力或“生成”注意力,对输出变量选择性地更新。不同的注意力机制可以用相同的计算工具实现。 综上,有别于 NTM 由信息内容和存储位置共同决定存储器读写,MANN 的每次读写操作会选择最近利用的存储位置,这种选择是和时间相关的,因此读写策略完全由信息内容和绑定时间所决定。MANN 实现了知识的高效的归纳转移(Inductive transfer)——新知识被灵活地存储访问,基于新知识和“长期”经验对数据做出精确的推断。 研究者使用实验数据集 MNIST 和 Omniglot,为了节省训练时间,图片被规则化成20×20大小,对比算法为 LSTM(如图19和表1所示)。 图19  MANN与LSTM对比结果 图19 MANN 与 LSTM 对比结果 请看图19(b),在5分类中,结果是在第2次学习时候,epoch 达到40000次后,准确率就已经到0.8左右了。并且可以看出,随着 MANN 的重复学习,学习知识的速度有一个陡峭的上升。这跟人类的学习曲线有些类似。 表1 MANN 与 LSTM 对比结果表 表1  MANN与LSTM对比结果表 本节到这里就结束了,我们做一个强化学习和 NTM/MANN 的总结。 强化学习:强调如何基于环境而行动,以取得最大化的预期利益。也可以说是 Agent 不停适应环境的能力,或者可以说是形成“条件反射”的一种方式。 NTM/MANN:从学到的知识中记忆、归纳,形成规则应用到其他事物的判断中的能力。当然目前只能做到记忆并没有太多的归纳或推导能力,但未来可以尽情想象。 #### 终极理想:终身学习 前面花了一些篇幅来讨论两种记忆模型,因为“记忆”是我们知识获取、知识形成的基础要素,就像前文所提到的,这一切都为一个最终目标——让机器能够自主地终身学习(Life-long Learning)。 图20  终身学习示意 (引用自 ELLA: An Efficient Lifelong Learning Algorithm。) 图20 终身学习示意 (引用自 ELLA: An Efficient Lifelong Learning Algorithm。) 在 ICML2013 的会议上,Paul Ruvolo 和 Eric Eaton 首次在论文《An Efficient Lifelong Learning Algorithm》中提到了终身学习的概念。 在吸收论文中终身学习的概念后,一个终身学习系统应包含以下四个基础部分。 - 知识库(Memory) 知识库是图中下方的圆柱体,这里存储了前期学到的知识。它由输入和输出构成,输入的一部分是新知识直接存储,另一部分是已有知识的归纳推导,形成一种规则;而输出则是知识的应用或传递。 - 控制器(Controller) 控制器对 Read 和 Write 直接进行操作,并考虑到学习的顺序和指向性;而顺序、指向性、以及随着时间推移变化的知识存储将对泛化能力与学习代价产生影响。 - 知识转移或知识使用(Read) 知识转移从知识库中选择对新知识(目标领域,Target Domain)有帮助的旧知识(源领域,Source Domain)进行迁移。或是直接将旧知识(有可能是一条规则,有可能是之前原始知识的存储)利用起来。 - 知识归纳(Write) 知识归纳是终身学习系统中至关重要的环节,以保证知识库能得到及时的更新。主要有两个方面:一部分是新知识的直接存储,另一部分是已有知识的归纳推导,形成一种规则或自有逻辑并存储下来。要求存储的规则或逻辑有一定的泛化能力。 ### 总结 获取终身学习是每一位研究强人工智能的科学人员的梦想。而强化学习是将环境的刺激纳入到目前的模型中,让 AI 有“适应”环境的能力。人类的学习机制从某种意义上说也是一种适应环境的行为:从一次或少数几次的学习中,推导或归纳出一个规律,并将这个规律应用到新的判断中,这种能力将可能帮我们打开强人工智能的大门。