深度强化学习介绍

2018年7月24日1,8570

作者水平有限,现学现卖,逐步施工。

最后更新于 2018.5.17

概述

强化学习的目标是需要学习一种策略,使得对于每一个状态,决策 AI 的动作。比如围棋的局面就是状态,我们想得到一种局面下的较优动作。

如果把动作看做对状态这一个属性的标记,强化学习就可以类比为监督学习,这样策略就相当于一个分类或者回归器,主要的区别是,标记信息往往需要通过尝试、和环境进行交互获得。算法根据环境给予的反馈来调整策略。

强化学习任务通常使用马尔可夫决策过程描述,AI 处在一个环境中,每个状态为 AI 对环境的感知。当 AI 执行一个动作后,会使得环境按概率转移到另一个状态;同时,环境会根据奖励函数给 AI 一个反馈。综合而言,强化学习主要包含四个要素:状态、动作、转移概率以及奖励函数。

K-摇臂赌博机 模型

赌徒投入一个硬币后,选择一个摇杆,摇杆有一定的概率吐出硬币,这个概率赌徒并不知道。赌徒的目标就是通过找到一个策略来使自己在固定的成本下,收益最大。

如果要最大化单步奖赏,我们要知道每个动作的期望奖励,之后选择奖励最大的动作来执行。若每个动作的奖励固定,则只需要将每个动作尝试一遍。但通常情况下,动作的奖励服从概率分布,因此需要进行多次的尝试。那么就需要花费一定的成本进行探索。

\epsilon 贪心 :每次尝试时,以 \epsilon 的概率进行探索,动作服从均匀分布;以​ 1-\epsilon  的概率利用,即选择当前最优的动作。

有时用 softmax 基于每个动作的期望回报计算每个动作的概率。

从 DQN,PG 到 DDPG

Q-Learning

1989 年 Watkins 提出了 Q-Learning 方法,1992 年和 Dayan 证明了其收敛性。

对于一个状态,执行了某个动作,由于很多动作的反馈并不是即时的,比如下棋是有输赢的,通常希望未来的期望奖励最高。

有时还会引入折扣因子 \lambda , 如果在某个时刻获得了奖励 R,对 t 个单位时间前的 动作的期望奖励 贡献是 R * \lambda ^ t 。

我们试图得到一个 Q 函数,使得对于一个状态和动作,能够计算期望奖励。

如果状态空间和动作空间都是有限离散的,转移概率是可估计的,那么就很容易用动态规划来求解 Q 函数。

策略就是,每次选择 Q 最大的动作,当然一般要通过探索来迭代估计转移概率,这种方法称为 Q-Learning,值函数方法。

Deep Q-learning

2013年,DeepMind 在 NIPS workshop上提出了 Deep Q-learning,主要工作是能让 AI 从像素输入学会完 Atari游戏,后来进行了一些改进后上了 2015 年的 nature 封面。

如果状态空间是连续的,动态规划的状态数就是无限的,所以我们用深度学习网络去拟合这个 Q 函数,这就是 DQN。

通常 DQN 的实现中,会把收集的(状态、动作、执行动作后的状态和奖励)存在内存中,训练的时候多次使用,称为 memory replay。

注意到每个(状态,动作)的 Q 值要拟合 (当前得到的奖励加上(执行动作后的新状态,新动作)的 Q 值),一个函数拟合自己可能引入额外的噪声,所以通常使用一个延迟更新的函数 Q’ 来求新的 Q 值,称为 target network。

DQN 的改进

2015 年,DQN 有三个主要改进,包括 Double DQN,Dueling Network 和 Prioritized Replay。

Double DQN 是在引入了 target network 后,改进了 Q 值的计算方法。

考虑到 Q 值和状态,动作都相关,但我们实际上更注重动作带来的奖励,Dueling Network 对网络结构做了改进。

Prioritized Replay 探讨在 replay memory 采样的优先级问题。

前两者都比较简单和有效,通常只要改三四行代码,但第三者需要维护 log 级的数据结构,带来的额外时间消耗有时特别大。

Policy Gradient

2000 年 Richard S. Sutton 在 NIPS 上提出了 Policy Gradient 方法,PG 看起来是一种更直接的做法,直接以状态作为输入,输出一个动作,根据获得的奖励来梯度下降更新一个动作出现的概率。

Deep Deterministic Policy Gradient

DDPG 运用了演员-评论家框架,把 DQN 和 PG 混合了起来。

如果动作空间也是连续的,那么就无法直接取到最大的 Q 值,那么我们再用个深度学习网络,称为演员,演员的任务就是选 Q 值大的动作,演员的梯度来自值函数的估计网络(评论家)。

一个理解 DDPG 的例子 (抖机灵)hzwer:如何做出 2π 分熟的牛排?

强化学习的研究问题

Pendulum 是一个倒立摆,目标是控制它立起来。

Continuous Lunar Lander 是通过调整方向和动力,让一个飞行器降落。

Bipedal Walker 是控制一个双足动物行走,跨越障碍,目前这个问题最好的解是通过遗传算法获得的。

Breakout 是 Atari 中的一个游戏。

Vizdoom 是基于第一人称射击 Doom 游戏的人工智能研究平台。

TORCS 是个简单的赛车游戏。

Minecraft 有研究在《我的世界》游戏中搭建一些简单环境训练 AI。

StarCraft 星际目前基于深度学习的 AI 都比较傻。

强化学习的困难

环境探索难,数据昂贵

许多环境的输出动作组合十分的复杂,客观上需要大量的模拟器生成的数据,但复杂的模拟器运行缓慢,获取数据的代价很高,目前有研究试图加速探索,比如好奇心驱动的超级玛丽 AI。

同时,算法的样本利用率非常低,即使经验回放,通常一个样本仅用于训练几次就会被丢弃。

奖励函数很难设计

我们需要加入合适的先验,但模型很多时候会找到作弊的手段。(一个例子(抖机灵)hzwer:人工智能达到了什么程度?)。有的时候奖励函数还会引入新的偏见影响收敛。

奖励函数的值不能太稀疏,否则大量的动作没有即时反馈非常难训。

这一点和对状态做特征工程一样令人头痛,DQN 的最大贡献之一就是告诉我们可以用网络提取特征,替代特征工程,再在强化学习里大量做特征工程令人觉得是在开倒车。

系统的复杂性

深度学习的算法都是由大量的小部件组合起来的,每个小部件都有大量的研究和使用经验。

对于从像素训练的游戏,卷积神经网络的训练增加了这种系统的复杂性,提取特征给 AI 训练又是一个包含了分类,检测,语义分析等复杂问题的组合。

有一些文章指出,强化学习的算法复现困难,而且超参数对于算法性能的影响极大,被称为强化学习劝退文。

甚至现在需要有大量文章,探讨如何复现一个强化学习的基准算法。

大量探讨强化学习理论的论文,实验都做的很差劲,一篇论文里捧的很厉害的改进结果可能比不过加一些小技巧的基准算法,让人没法去评价一个工作。

由此带来的一大问题是,很多论文研究的结论都不可信,看起来大部分的强化学习方向的论文都在 Half-Cheetah,Hopper 这样一些简单控制问题的环境上做实验,基本上就是学习一种运动模式,不断重复。

好一点的会做做 Atari,但是很大一部分 Atari 游戏的逻辑非常简单。比方说 Pong,就是根据球的运动方向做简单判断。一般是把图放缩为 84 * 84 当输入,其实把每行、列求和后当输入都能训练得好好的,说明卷积其实也没有学到非常高级的东西。

我的一些实践

NIPS 2017 Learning to Run

由斯坦福神经肌肉生物力学实验室主办的 NIPS 2017 的 5 个官方挑战赛之一。

要求开发一个控制器,使符合生理学的人体模型能够尽可能快地完成障碍跑。

环境提供的输入信息是41维的0到1实数向量,包括下肢关节的位置,角度,速度,障碍信息等,根据这些信息我们需要输出18维的0到1实数向量,决策下肢肌肉的动作;环境具有随机性,障碍的大小和位置是不确定的,而且输入信息中只有模型前方最近的一个障碍。

比赛难点主要就是之前说到的,数据昂贵。官方提供的模拟器的计算速度很慢,每轮障碍跑在单核 CPU 上的模拟时间超过一个小时。

这件事情业余做了 2 个月左右,大概就干了两件事情。

1. 实现了一个不错的 DDPG 算法。因为刚入门炼丹的原因,抄开源代码,一个多星期才成功跑出最简单的 CartPole。

主要是借助了

做的特征工程和并行环境的代码,以及调了一点参数。

2. 用了一下监督学习比赛中常见的 ensemble 方法,训练多个 actor 和 critic,每次让 actor 们出一堆动作,让 critic 投票来选,这样显著降低了跑摔的次数。

主要动机是发现 actor 相比于 critic 非常之傻,后续可能还有一些相关的工作来探讨这个问题。

想进一步了解可以移步 hzwer/NIPS2017-LearningToRun

代码写的非常的丑现在都不忍直视,拿了第二名骗了一块 Titan V(捂脸),今年似乎还有新的一届,可能能做的好点,据说第一名用了超宽网络的 PPO,Youtube 上有他们的视频。

强化学习和视觉

想把强化学习的方法用在计算机视觉相关问题上,最直接的一个想法就是能不能训练一个会画画的人工智能,做了一段时间,4月份 deepmind 挂了一篇文,基本是一个思路,但是看起来还有很多问题没解决,可能今年暑假我们也会出一点成果,欢迎关注。

具体先就说一点,目前强化学习研究中用卷积网络提特征的游戏,对于卷积网络的要求通常不高,因为针对单个游戏不需要考虑过拟合的问题。

一些经验

  1. 尽可能加快实验迭代的速度,一方面是先降低目标,尝试小模型,一次尝试超过三五个小时的话,脑袋很容易就凉了;另一方面考虑工程上的加速,用工具测一下程序的时间消耗都在哪,我曾经发现一半的时间在用 numpy 做四舍五入。考虑一下并行,这种加速带来的提升是立竿见影的,迟早都得做。
  2. 实验的可复现性非常重要,一个代码运行以后就不修改了,新实验干脆把原来的文件夹拷贝一份改个名字。
  3. 把有用的数据全都可视化,便于发现问题。

说点什么

提醒
avatar