2016年的AI,一场史无前例的技术营销

版权归作者所有,任何形式转载请联系作者。
作者:insightlight(来自豆瓣)
来源:https://www.douban.com/note/602333108/

2016年12月29日,大概又是一个会被载入史册的日子。名叫SkyNet,哦不,是”Master”的围棋AI,开始了第一次对人类的血洗。

在奕城的第一晚,Master十战全胜;第二日,横扫韩国第一人朴廷桓九九段、世界第一人柯洁,比分都是2比0;第三日,陈耀烨九段、金庭贤五段、范廷钰九段、芈昱廷九段和唐韦星九段依次落马;再之后是古力、时越、金志锡、井山裕太;到了1月4日,聂卫平老先生以7目半落败。最终战绩,Master 60胜0负1平(平的那局是因为掉线)

自此,Artificial Intelligence(AI),这个在2016年已经如日中天的buzzword,再一次传遍大街小巷。人们沉浸在对AI的崇拜、慌乱与恐惧之中,然而作为吃瓜群众的笔者却在想一个问题:如果DeepMind没有事先与各国棋院通气,整个事件如何能进行得如此顺利,在时间上如此紧凑?所有重要的世界高手,都在短短几天的时间窗口内腾出了时间,如果说没有提前策划和组织,实在有点难以置信。掐指一算自从3月份AlphaGo的横空出世,DeepMind已有9个月时间没有在圈外露脸,大概它也感受到了营销的压力吧。

其实纵观2016年,在阿尔法狗狗的带领之下,AI界隔三差五地在圈内外制造着骚动:3月,除了人尽皆知的AlphaGo事件,李开复关于人工智能博士200w+美金年薪的文章刷屏;4月,Google著名的深度学习框架TensorFlow发布分布式版本;6月,Prisma上线,红极一时;8月,Google发布基于深度学习的NLU框架SyntaxNet; 9月,Google上线基于深度学习的机器翻译,索尼用人工智能写了两首歌;11月,计算机视觉学术大牛李飞飞老师下海进入工业界;12月,百度宣布他们的深度学习系统在语音识别上超过人类,DeepMind在NIPS16会议上宣布DeepMind Lab开源。一切的一切,都在各大媒体冠以【重磅】开头的新闻标题之下,一次次地牵动着广大吃瓜群众的神经——然而这些成就实际上离我们的生活又是那么的遥远。

在科技的历史上,从未有任何一项科技,在它的大规模真实应用之前,有持续一年甚至几年的营销运动。在这个风口之上,在这个AI几年的造势运动把人们的期望与恐惧推上一个历史顶点,而其真正落地应用又遥遥无期的一个尴尬节点,是时候冷静下来回顾一下AI的营销史了。

一、一些概念和历史

有几个概念需要先明确一下,因为我发现在今日媒体的狂轰滥炸之下,有大批AI民科是分不清像“人工智能”、“机器学习”、“深度学习”这些概念的关系的(例如我认识的非科班出身的人有90%认为机器学习=深度学习)。当然这些概念的含义也一直在“与时俱进”,不过学界还是有一个相对统一且合理的认知,可以帮助我们阐述问题。下面这张图描述了其中最重要的几个概念之间的关系
“人工智能”这个buzzword,常常会因为营销或者新闻报道的需求而被赋予不同的含义,其外延有时等同于“机器学习”,有时不等同,所以最外圈的这个等号并不完全准确。不过在2016年被大家普遍讨论的这些“AI”,可以认为基本上就是机器学习。内部的四个小圈则是学术上有确定外延的四个概念,代表了当前最重要的四个问题领域,是需要明确的重点概念。

有监督学习(supervised learning)——让机器观测到一些输入,并告诉机器在这些输入下应该产生什么样的输出。机器通过这些数据学习出一个模型,之后给它新输入的时候,它能够根据模型预测应该产生什么样的输出。比如机器看到一个图片,可以判断图片中的物体属于哪一个分类。

无监督学习(unsupervised learning)——让机器观测到一些输入,而没有标准输出,让机器自行去总结这些输入数据有什么统计特征,并生成有意义的产出。例如自动把大批文章聚成相似的几类,又例如给计算机看一些小狗小猫的照片,让计算机自动生成一些新的(与看过的相似但又不同的)小狗小猫的照片。

增强学习(reinforcement learning)——让机器观测到一些输入,并让机器根据输入做特定动作(action)。这些动作导致机器获得收益或者惩罚(reward)。机器通过增强学习优化它的动作策略(strategy),使得它的长期收益最大化。下棋就是这一类典型的问题,strategy就是行棋策略,reward就是赢棋。

深度学习(deep learning)——事实上不是一类问题,而只是一种方法,一种通过多层神经网络来构建上述三种问题所需要的模型的方法。

回到历史。这一波的AI热,最早应归功于Hinton老头子的文章《A fast learning algorithm for deep belief nets》这篇文章是2005年写的,截至2017年1月14日已有5000+的引用,足见其影响力)这篇文章实际上是用一种无监督学习的方法实现了对原始数据逐层抽取深度特征,而这些深度特征可以被用为有监督学习的特征来提高有监督学习的准确率。这解决了长久以来神经网络“无法做深”的痛点(原因是训练信号会随着深度增加而被稀释,有兴趣的读者可查阅相关资料),算是一个比较大的贡献。不过当时这个文章传达的大方向是用无监督学习的方法抽取特征(这个过程叫做pre-training),并没有把重点放在有监督学习本身的模型上,所以当时的同学们对于有监督/无监督在方向选择上是有点迷茫的。

这种迷茫直到2012年还存在。这一年的一件大事是Andrew NG等人的Google Brain团队,搞了一个庞大的分布式深度学习,在ImageNet图片物体分类竞赛中把对手远远甩在了身后(《Building High-level Features Using Large Scale Unsupervised Learning》)前面已经说过,物体分类是一个有监督学习任务,但是由于Hinton老爷子定下的无监督学习基调,Andrew NG等人还是把重心放在了无监督学习生成特征上面,并且做出了那幅著名的“机器学习出来的猫”。有趣的是,在2012年的NIPS上,Hinton和NG的团队同时放弃了pre-training。失去了pre-training的帮助,就需要其他方法解决训练信号被稀释的问题,Hinton团队的方法是换了一种叫做ReLU的激活函数( 《ImageNet Classification with Deep Convolutional Neural Networks 》),NG团队的方法则是怼机器,大量的机器(《Large Scale Distributed Deep Networks》)。Hinton团队同时还抛出了CNN应用到ImageNet上的表现,CNN和ReLU这两个东西非常重要,成为此后深度学习研究的标配。结果Hinton团队这篇文章的引用数有8000多,而NG团队的两篇分别是700多和1000多。NG的营销能力强,学术创新上却总是比Hinton老爷子慢半拍。Anyway,自从12年NIPS这两篇文章之后的一段时间,大家对无监督学习就不怎么感冒了。
2012年Andrew NG团队无监督学习生成的猫脸图片。图片来源:New York Times
也是从2012年的ImageNet竞赛开始,AI进入第一个营销高潮。当时的人们对于计算机识别小猫小狗这种事情还觉得很新鲜,于是接下来科研圈的开始对此类事情趋之若鹜。几乎每个做机器学习的实验室都会尝试一把在State-of-the-art的模型上做一点哪怕是很小的微创新,希望能产生ImageNet准确率上一点哪怕是很小的提升,一旦成功了,就可以说自己是新的State-of-the-art。从那以后,大家开始只关心实验的准确率,越来越少的人关心模型本身的理论价值。AI研究的方法论,从传统科学的重视推理论证,变成了快速尝试+总结相关性(也就是所谓的“大数据思维”)。毕竟准确率数字是很好拿出去说的,理论价值却很难讲清楚。 AI自此进入营销时代。

在AI学术界这一翻天覆地的变化背后,Andrew NG功不可没。深度学习理论上的重要突破大多都不是归属于他的,然而他做了几件重要的事情:2008年发起“Stanford Engineering Everywhere”(SEE)项目,把自己的机器学习课程曝光给全世界人民;2011年组建了Google Brain项目,这个项目初期的最主要产出之一就是后来被媒体大书特书的那张无监督学习出来的猫脸,并且这个结果在报道的时候给人一种“机器有了自主学习能力”的认知;2012年创立Coursera,在MOOC社区中进一步营造出一种AI大繁荣的景象。NG大概是这几年媒体出镜率最高的AI学术圈人士。与其说是一位科学家,Andrew NG的角色更像是一位优秀的AI产品经理及营销人员,他的营销能力在圈内早已得到公认。关于NG的营销能力,在NIPS 2016会议上还有一个有趣的小细节,将会在后面提到。

回到我们的时间线,鉴于2012年底深度学习在有监督学习上的巨大成功,一段时间内大家忙于把这项技术推广到各个应用领域跑马圈地(其实主要还是图像和语音),暂时忘掉了无监督学习和生成猫脸的事情。到了2014年,当各个领域都被圈的差不多了,学术界在苦苦寻找下一个噱头的时候,大神Ian Goodfellow通过一个叫做“干”的东西(GAN,Generative Adversarial Network)把无监督学习重新带回了人们的视线。“干”干的就是“给计算机看一些小狗小猫的照片,让计算机自动生成一些新的(与看过的相似但又不同的)小狗小猫的照片”这样一件事情,不同点在于,它干的非常不错。一时间,AI学术界迅速高潮了,纷纷竞争起生成图片(以及语音、音乐等各种其他东西)的生意来。大家也并不关心我们为什么需要生成这些图片(相比之下语音合成和自动生成音乐反而更容易理解一些),大概只是觉得“能干这件事情看起来就很牛逼”,于是就做了,而且做的越来越好。下图是Ian Goodfellow在NIPS 2016上讲GAN的Tutorial里展示的一个生成小动物的demo(《NIPS 2016 Tutorial: Generative Adversarial Networks》)。
GAN生成的小动物图片。图片来源:Ian Goodfellow, NIPS 2016 Tutorial: Generative Adversarial Networks
与此同时,DeepMind在增强学习上的努力,则一直在相对低调地进行。增强学习在很长一段时间内被认为是“仅停留在学术研究”的存在,因其难以降下来的巨大状态空间和动作空间,很难做出一个可展示又足够吸引吃瓜群众的demo。因而在AlphaGo诞生之前,增强学习的研究一直处于一个不温不火的状态。一个叫做“DQN”的东西的出现打破了这个局面。通过把深度学习应用在strategy的学习更新上,巧妙避开大状态空间和动作空间,DQN使得在一个相对小的多的参数空间内训练成为可能(《Playing Atari with Deep Reinforcement Learning》)。这是一个了不起的成就,为后来的AlphaGo奠定了基础。这个伟大想法产生的时间在2013年以前(前述文章在2013年发表),而直到2015年AlphaGo问世之后才被广为传颂。可见一个漂亮的demo是多么重要。

再然后,就是大家都知道的事情了。

二、一些奇怪的现象

AI围棋战胜人类,本身是一个伟大的成就。然而在这个伟大浪潮推动下的AI学术大跃进与创业热中,却出现了很多奇怪的现象。

理性地分析AI这个事情,至少应该提三个问题:1. 这玩意到底做不做的出来;2. 假如这玩意能做出来,那么它做出来以后到底有没有应用前景;3. 假如这玩意能做出来且有应用前景,它会不会毁灭人类。这三个问题是层层递进的关系,对1的答案是肯定的讨论2才有意义,对2的答案是肯定的讨论3才有意义。于是有了第一个奇怪的现象:大部分的吃瓜群众,直接跳过了1、2而去关注3。甚至他们中的乐观主义者,直接跳过123,开始充满自信地迎接这个“未来趋势”了。是Alpha狗狗给我们的信心过于足了吗?

要知道,真正的AI工作者甚至对问题1都没有足够的自信。不错,AlphaGo毫无疑问“已经做出来了”,但不要忘了,围棋再复杂,它仍然是一个游戏;从一个两页纸即可将规则全部讲明的游戏到一个充斥着复杂场景的现实世界,有着巨大的鸿沟需要跨越。在NIPS 2016上,可以明确地感受到,DeepMind已经处在一个深陷游戏之中无法自拔的尴尬状态——不仅几乎所有的paper都是以游戏为demo的,甚至有些研究的目标都是奔着游戏而去的(例如有的工作研究人类玩游戏时是否用到了先验知识,有的工作研究人类玩游戏时的学习曲线,分的很细)。游戏在这些的研究中并不只是一个用来展示的demo,而就是研究的核心。DeepMind在AlphaGo之后一直宣称的进军医疗这件事,却在NIPS 2016上几乎不被人提起。

有意思的是,擅长营销的Andrew NG在NIPS 2016的演讲还趁机轻踩了一下他不太涉足的无监督学习和增强学习。他在白板上画了这样三条曲线。
意思是说,有监督学习的应用在2011年起步,到现在已经比较成熟了;无监督学习刚刚起步;增强学习的真实应用则还是遥远的未来。虽然脱不开为自己营销之嫌,这个说法本身还是比较靠谱的。连李开复也在几天前发的一篇长文《AI创业的十个真想》中,白纸黑字地说到“AlphaGo本身没有商业价值”。像下围棋这样的增强学习技术应用到真实的生活生产,产生游戏之外的价值,不说是一个遥远的未来,至少还是一个技术上比较不确定的事情。

第二个奇怪是没有人问问题2。普通人并不奇怪,奇怪的是产品经理这样一群人,他们在平日工作中对一个产品的应用前景的拷问,可以苛责到极致;而到了AI这件事上,却看不到一篇在产品技术层面客观剖析应用前景的文章。一个最明显的例子是最近大热的聊天机器人。不知道“聊天机器人将是下一代的操作系统”这样一个牛皮是如何在业界传播开来的?再重复一遍,“聊天机器人将是下一代的操作系统”,这话听上去就需要很多解释和论证吧?反正每当我在一个网站正常服务点不进去,不得不求助在线客服或者是电话客服(指人工客服)的时候,就已经很不爽了。当然不是说别人想法都和我一样,但是对于一个与用户直接交互的界面,是不是至少应该做个用户调研,再说“聊天机器人将是下一代的操作系统”这样的话?

第三个奇怪有关成本。Facebook围棋项目负责人田渊栋前日在自乎专栏上写过这样一段文字:

“在八月份美国围棋大会上,我有幸见到了AlphaGo的主要贡献者黄士杰(AjaHuang)和樊麾。我问他们,我们用了大概80到90块GPU来训练模型,我是否可以在演讲时说我们用了AlphaGo百分之一的GPU?那时Aja神秘地笑了笑说:具体数字不能讲。不过,也许小于百分之一吧。”

一块GPU大约两万人民币,算算总共要花多少钱吧。这还远不是全部,还有以月记的计算时间、电力/带宽消耗,以及那么多份200w美金的工资。

当然这样估算成本未必科学。我想表达的是,唯独在AI这件事上,人们似乎表达出了对于成本问题前所未有的宽容。这宽容体现在除了真正在一线做AI的工程师,极少有人关注成本问题。另外需要澄清的是这里疑问的点是“人们不关注”,并不是想表达“AlphaGo劳民伤财了”这个意思。个人内心里其实是把AlphaGo当做一件伟大的艺术品来看待的,而艺术品是无价的——只有在讨论艺术品的时候可以用“无价”这个度量,对于商业产品不行。

三、该怎么看待这件事情

不要预期过高,不要预期过高,不要预期过高。泡沫时代的我们已经习惯了对未来事物预期过高。被透支的预期甚至成了维持经济的重要支柱。只是每一次泡沫破灭都会很疼。很怀念曾经那个时代,在那个时代里,科学技术的进步源于对真理的信仰与热爱,而不是为了填补预期与现实的反差。然而那个时代已经回不去了。

勤奋一些,学习真相。巴菲特从来不投资自己不熟悉的业务。如果不能判断一件事情,那么就应该真正学习它,知道它是什么东西,在积累了足够知识之后做出判断。如果少一些分不清“深度学习”和“机器学习”的关系的人,或许这个世界也会少一些错误的风向。接受无知而被营销者和媒体的观点摆布,是一件非常可怕的事情。就像我们有时不能从政府那里得到真相,在AI这个学界和工业界各种势力利益关系已经非常庞大复杂的领域内,仅凭我们听到的,恐怕很难得到真相。

如果AlphaGo仅仅是AlphaGo,那该多好啊。

【转载】【David Silver强化学习公开课之一】强化学习入门

【David Silver强化学习公开课之一】强化学习入门

【转载请注明出处】chenrudan.github.io

David Silver:http://www0.cs.ucl.ac.uk/staff/d.silver/web/Home.html

本文链接:https://chenrudan.github.io/blog/2016/06/06/reinforcementlearninglesssion1.html

本文是David Silver强化学习公开课第一课的总结笔记。第一课主要解释了强化学习在多领域的体现,主要解决什么问题,与监督学习算法的区别,完整的算法流程由哪几部分组成,其中的agent又包含什么内容,以及解释了强化学习涉及到的一些概念。

本课视频地址:RL Course by David Silver – Lecture 1: Introduction to Reinforcement Learning

本课ppt地址:http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching_files/intro_RL.pdf

文章的内容是课程的一个总结和讨论,会按照自己的理解来组织。个人知识不足再加上英语听力不是那么好可能会有一些理解不准的地方,欢迎一起讨论。

建了一个强化学习讨论qq群,有兴趣的可以加一下群号595176373或者扫描下面的二维码。

1

1. 强化学习是什么

强化学习是多学科多领域交叉的一个产物,它的本质就是解决“decision making”问题,即学会自动进行决策。在computer science领域体现为机器学习算法。在Engineering领域体现在决定the sequence of actions来得到最好的结果。在Neuroscience领域体现在理解人类大脑如何做出决策,主要的研究是reward system。在Psychology领域,研究动物如何做出决策,动物的行为是由什么导致的。在Economics领域体现在博弈论的研究。这所有的问题最终都归结为一个问题,人为什么能够并且如何做出最优决策。

强化学习是一个Sequential Decision Making问题,它需要连续选择一些行为,从而这些行为完成后得到最大的收益最好的结果。它在没有任何label告诉算法应该怎么做的情况下,通过先尝试做出一些行为得到一个结果,通过判断这个结果是对还是错来对之前的行为进行反馈,然后由这个反馈来调整之前的行为,通过不断的调整,算法能够学习到在什么样的情况下选择什么样的行为可以得到最好的结果。

强化学习与监督学习有着不少区别,首先监督学习是有一个label的,这个label告诉算法什么样的输入对应着什么样的输出,而强化学习没有label告诉它在某种情况下应该做出什么样的行为,只有一个做出一系列行为后最终反馈回来的reward signal,这个signal能判断当前选择的行为是好是坏。其次强化学习的结果反馈有延时,有时候可能需要走了很多步以后才知道以前的某一步的选择是好还是坏,而监督学习做了比较坏的选择会立刻反馈给算法。强化学习面对的输入总是在变化,输入不像监督学习是独立同分布的。而每当算法做出一个行为,它影响了下一次决策的输入。

2. 强化学习组成

1

图1 强化学习组成部分(图片来源[1])

强化学习决策流程见上图。需要构造出一个agent(图中的大脑部分),agent能够执行某个action,例如决定机器人超哪个方向走,围棋棋子下在哪个位置。agent能够接收当前环境的一个observation,例如当前机器人的摄像头拍摄到场景。agent还能接收当它执行某个action后的reward,即在第t步agent的工作流程是执行一个动作AtAt,获得该动作之后的环境观测状况OtOt,以及获得这个动作的反馈奖赏RtRt。而环境environment则是agent交互的对象,它是一个行为不可控制的对象,agent一开始不知道环境会对不同action做出什么样的反应,而环境会通过observation告诉agent当前的环境状态,同时环境能够根据可能的最终结果反馈给agent一个reward,例如围棋棋面就是一个environment,它可以根据当前的棋面状况估计一下黑白双方输赢的比例。因而在第t步,environment的工作流程是接收一个AtAt,对这个动作做出反应之后传递环境状况和评估的reward给agent。reward奖赏RtRt,是一个反馈标量值,它表明了在第t步agent做出的决策有多好或者有多不好,整个强化学习优化的目标就是最大化累积reward。例如在射击游戏中,击中敌方的一架飞机,最后的得分会增加,那么这一步的reward就是正值。

3. 一些变量

history是所有动作、状态、奖赏的序列,Ht=A1,O1,R1,,At,Ot,RtHt=A1,O1,R1,…,At,Ot,Rt

environment state,SetSte,环境当前的状态,它反应了环境发生什么改变。这里需要明白的一点是环境自身的状态和环境反馈给agent的状态并不一定是相同的,例如机器人在走路时,当前的environment状态是一个确定的位置,但是它的camera只能拍到周围的景象,无法告诉agent具体的位置,而拍摄到的照片可以认为是对环境的一个observation,也就是说agent并不是总能知道环境是如何发生改变的,只能看到改变后的一个结果展示。

agent state,SatSta,是agent的现在所处状态的表示,它可以是history的任何函数。

information(Markov) state,它包含了history的所有有用信息。一个状态StSt有马尔可夫性质是指下一个时刻的状态仅由当前状态决定,与过去状态无关。这里定义可以看出environment state是有马尔可夫性质的(这个概念不明白可以暂时不管)。

如果说environment是Fully Observable的,那么就是说agent能够直接看到环境当前的状态,在这种情况下agent state与environment state是相等的。而如果说environment是Partially Observable Environments,那么就是上面机器人的那个例子,agent能获取到的不是直接的环境状态。

4. Agent的组成

一个agent由三部分组成Policy、Value function、Model,但这三部分不是必须同时存在的。

Policy,它根据当前看到的observation来决定action,是从state到action的映射。有两种表达形式,一种是Deterministic policy即a=π(s)a=π(s),在某种状态s下,一定会执行某个动作a。一种是Stochastic policy即π(a|s)=p[At=a|St=s]π(a|s)=p[At=a|St=s],它是在某种状态下执行某个动作的概率。

Value function,它预测了当前状态下未来可能获得的reward的期望。Vπ(s)=Eπ[Rt+1+rRt+2+|St=s]Vπ(s)=Eπ[Rt+1+rRt+2+…|St=s]。用于衡量当前状态的好坏。

Model,预测environment下一步会做出什么样的改变,从而预测agent接收到的状态或者reward是什么。因而有两种类型的model,一种是预测下一个state的transition model即Pass=p[St+1=s|St=s,At=a]Pss′a=p[St+1=s′|St=s,At=a],一种是预测下一次reward的reward model即Ras=E[Rt+1|St=s,At=a]Rsa=E[Rt+1|St=s,At=a]

因而根据是否选取这三个部分agent可分为下图中红色字体标出来的五种类型(这里有一个迷宫的例子很好,建议看原视频1:08:10起)。Model Free是指不需要去猜测environment的工作方式,而Model based则是需要学习environment的工作方式。

1

图2 Agent的分类(图片来源[1])

5. 探索和利用

强化学习是一种试错(trial-and-error)的学习方式,一开始不清楚environment的工作方式,不清楚执行什么样的行为是对的,什么样是错的。因而agent需要从不断尝试的经验中发现一个好的policy,从而在这个过程中获取更多的reward。

在这样的学习过程中,就会有一个在Exploration和Exploitation之间的权衡,前者是说会放弃一些已知的reward信息,而去尝试一些新的选择,即在某种状态下,算法也许已经学习到选择什么action让reward比较大,但是并不能每次都做出同样的选择,也许另外一个没有尝试过的选择会让reward更大,即Exploration希望能够探索更多关于environment的信息。而后者是指根据已知的信息最大化reward。例如,在选择一个餐馆时,Exploitation会选择你最喜欢的餐馆,而Exploration会尝试选择一个新的餐馆。

以上是第一课的一些相关内容,主要是介绍了一些基础概念,从而对强化学习有一个基础的认识。

6. 引用

  1. http://www0.cs.ucl.ac.uk/staff/d.silver/web/Teaching_files/intro_RL.pdf

[转载]【重磅】无监督学习生成式对抗网络突破,OpenAI 5大项目落地

http://www.cnblogs.com/wangxiaocvpr/p/5966574.html

【重磅】无监督学习生成式对抗网络突破,OpenAI 5大项目落地

 

【新智元导读】“生成对抗网络是切片面包发明以来最令人激动的事情!”LeCun前不久在Quroa答问时毫不加掩饰对生成对抗网络的喜爱,他认为这是深度学习近期最值得期待、也最有可能取得突破的领域。生成对抗学习是无监督学习的一种,该理论由 Ian Goodfellow 提出,此人现在 OpenAI 工作。作为业内公认进行前沿基础理论研究的机构,OpenAI 不久前在博客中总结了他们的5大项目成果,结合丰富实例介绍了生成对抗网络,并对OpenAI 五大落地项目进行梳理,包括完善对抗生成网络(GAN)、完善变分推断(VAE)、提出GAN的扩展 InfoGAN,以及提出生成对抗模仿学习及代码。

 

 

 

OpenAI 旨在开发能够让计算机理解世界的算法和技术。

 

我们常会忽略自己对周遭世界的理解:你知道世界由三维环境构成,物体可以移动、碰撞、相互作用;人能行走、说话、思考;动物会吃草、飞翔、奔跑或者鸣叫;屏幕会显示经过编码的信息,内容涉及天气、篮球赛的结果或者 1970 年的事情。

 

这些海量信息就在那里,大都触手可及——其存在形式要么是现实世界中的原子,要么是数字世界里的比特。唯一的问题是如何设计模型和算法,分析和理解这些宝贵的数据。

 

生成模型是实现这一目标最值得期待的方法。训练生成模型,首先要大量收集某种数据(比如成千上万的图像、句子或声音),然后训练一个模型,让这个模型可以生成这样的数据。

 

其原理是费曼的名言:“做不出来就没有真正明白。”(What I cannot create, I do not understand.)

 

用于生成模型的神经网络,很多参数都远远小于用于训练的数据的量,因此模型能够发现并有效内化数据的本质,从而可以生成这些数据。

 

生成式模型有很多短期应用。但从长远角度看,生成模型有望自动学会数据集的类型、维度等特征。

 

生成图像

 

举个例子,假设有某个海量图像数据集,比如含有 120 万幅图像的 ImageNet 数据集。如果将每幅图的宽高设为 256,这个数据集就是 1200000*256*256*3(约 200 GB)的像素块。其中的一些样例如下:

 

 

这些图像是人类肉眼所见的样子,我们将它们称为“真实数据分布中的样本”。现在我们搭建生成模型,训练该模型生成类似上图的图像,在这里,这个生成模型就是一个输出为图像的大型神经网络,这些输出的图像称为“模型样本”。

 

 

DCGAN

 

Radford 等人提出的 DCGAN 网络(见下图)就是这样一个例子。DCGAN 网络以 100 个从一个高斯分布中采样的随机数作为输入(即代码,或者叫“隐含变量”,靠左红色部分),输出图像(在这里就是 64*64*3 的图像,靠右绿色部分)。当代码增量式变化时,生成的图像也随之变化——说明模型已经学会了如何描述世界,而不是仅仅是记住了一些样本。

 

网络(黄色部分)由标准的卷积神经网络(CNN)构成:

DCGAN 使用随机权重初始化,所以随机代码输入会生成一个完全随机的图像。但是,这个网络有好几百万的参数可以调整,而我们的目的是设置参数,让根据随机代码输入产生的样本与训练数据看上去相似。换句话说,我们想要模型分布与图像空间中真实数据的分布相匹配。

 

训练生成模型

 

假设我们使用最新初始化的网络生成 200 幅图,每次都从不同的随机代码开始。问题是:我们该如何调整网络的参数,让每次输出的新图像都更接近理想?需要注意的是,这里并非监督学习场景,我们也没有对 200 幅输出图像设定明确的预期;我们只是希望这些图像看起来跟真实的一样。

 

一个巧妙的处理方式是依照生成对抗网络(Generative Adversarial Network,GAN)方法。这里,我们引入另一个判别器网络(discriminator network,通常是一个标准的卷积神经网络),判断输入的图像是真实的还是生成的。我们可以将 200 幅生成的图像和 200 幅真实图像用作训练数据,将这个判别器训练成一个标准的分类器,其功能就是区分这两种不同的图像。

 

此外,我们还可以经由判别器和生成器反向传播(backpropagate),找出应该如何改变生成器的参数,使其生成的 200 幅样本对判别器而言混淆度更大。这两个网络就形成了一种对抗:判别器试着从伪造图像中区分出真实图像,而生成器则努力产生可以骗过判别器的图像。最后,生成器网络输出的结果就是在判别器看来无法区分的图像。

 

下图展示了两种从生成模型采样的过程。两种情况下,输入都是有噪声和混乱的,经过一段时间收敛,可以得到较为可信的图像统计:

 

VAE 学会产生图像(log time)

 

GAN 学会产生图像(linear time)

 

这令人兴奋——这些神经网络正在逐渐学会世界看起来是什么样子的!这些模型通常只有 10 亿参数,所以一个在 ImageNet 上训练的网络(粗略地)将 200GB 的像素数据压缩到 100MB 的权重。这让模型得以发现数据最主要的特征:例如,模型很可能学会位置邻近的像素更有可能拥有同样的颜色,或者世界是由水平或竖直的边构成。

 

最终,模型可能会发现很多更复杂的规律:例如,图像中有特定类型的背景、物体、纹理,它们会以某种可能的排列方式出现,或者在视频中随时间按某种方式变化等等。

 

 

更泛化的表现形式

 

数学上看,我们考虑数据集 x1,…,xn 是从真实数据分布 p(x) 中的一段。下图中,蓝色区域展示了一部分图像空间,这部分空间以高概率(超过某阈值)包含真实图像,而黑色点表示数据点(每个都是数据集中一副图像)。现在,我们的模型同样刻画了一个分布 p^θ(x) (绿色),将从一个单位 Gaussian 分布 (红色) 获得的点,通过一个(判别器)神经网络映射,得到了生成模型 (黄色)。

 

我们的网络是参数为 θ 的函数,调整这些参数就能改变生成出的图像分布。目标是找到参数 θ 可以产生一个较好匹配真实数据分布的分布。因此,你可以想象绿色分布从随机开始,然后训练过程迭代式改变参数 θ 拉长和压缩自己使得更匹配蓝色分布。

 

生成模型三种搭建方法

 

大多数生成模型有一个基础的设置,只是在细节上有所不同。下面是生成模型的三个常用方法:

 

  • Generative Adversarial Network(GAN)这个我们在上面讨论过了,将训练过程作为两个不同网络的对抗:一个生成器网络和一个判别器网络,判别器网络试图区分样来自于真实分布 p(x) 和模型分布 p^(x) 的样本。每当判别器发现两个分布之间有差异时,生成器网络便微整参数,使判别器不能从中找到差异。

     

  • Variational Autoencoders(VAE)让我们可以在概率图模型框架下形式化这个问题,我们会最大化数据的对数似然(log likelihood)的下界

     

  • PixelRNN 等自回归模型。训练一个建模了给定前面像素下每个独立像素条件分布的网络(从左到右,从上到下). 这类似于将图像的像素输入到一个 char-rnn,但是 RNN 水平和垂直遍历图像,而不是 1D 的字符序列

 

所有这些方法有各自的优缺点。例如,变分自编码器可以执行学习和在复杂的包含隐含变量的概率图模型上进行高效贝叶斯推断(如 DRAW 或者 Attend Infer Repeat 近期相对复杂的模型)。但是,生成的样本会有些模糊不清。GAN 目前生成了清楚的图像,但是因为不稳定的训练动态性很难优化。PixelRNN 有一个非常简单和稳定的训练过程(softmax loss),并且当前给出了最优的对数似然(产生出数据的可信程度)。然而,PixelRNN 在采样时相对低效,而且没有给图像以简单的低维代码。

 

OpenAI 5 大落地

 

我们对 OpenAI 做出的生成式模型非常兴奋,刚刚发布了四个对近期工作项目改进工作. 对每个贡献,我们同样发布了技术报告和源代码.

 

1. 完善对抗生成网络(GAN)

 

 

GAN 是非常值得期待的生成模型,不像其他方法,GAN 产生的图像干净、清晰,并且能够学会与纹理有关的代码。然而,GAN 被构建成两个网络之间的对抗,保持平衡十分重要(而且相当考验技巧):两个网络可能在解析度之间震荡,生成器容易崩溃。

 

Tim Salimans, Ian Goodfellow, Wojciech Zaremba 等人引入了一些新技巧,让 GAN 训练更加稳定。这些技巧让我们能够放大 GAN ,获得清晰的 128*128 ImageNet 样本:

 

[左]真实图像(ImageNet);[右]生成的图像

 

我们 CIFAR-10 的样本看起来也是非常清晰的——Amazon 为图像打标签的工人(Amazon Mechanical Turk workers)在区分这些图像和真实图像时,错误率为 21.3% (50% 的错误率代表随机猜测)。

 

[左]真实图像(CIFAR-10);[右]生成的图像

 

 

除了生成更好的图像,我们还引入了一种结合 GAN 和半监督学习的方法。这使我们在不需要大量带标签样本的前提下,在 MNIST、SVHN 和 CIFAR-10 获得当前最佳的结果。在 MNIST,我们对每个类仅有 10 个带标签的样本,使用了一个全连接的神经网络,达到了 99.14% 的准确率——这个结果接近已知最好的监督学习,而后者使用了 6 万个带标签的样本。由于为样本打标签非常麻烦,所以上述方法是很值得期待的。

 

生成对抗网络是两年多前才提出来的,我们期望在未来出现更多提升其训练稳定性的研究。

 

2. 完善变分推断(VAE)

 

在这项工作中,Durk Kingma 和 Tim Salimans 引入了一个灵活、可扩展的计算方法,提升变分推断的准确率。目前,大多数 VAE 训练采用暴力近似后验分布(approximate posterior),每个隐含变量都是独立的。最近的扩展工作虽然解决了这个问题,但由于引入的序列依赖,在计算上仍然称不上高效。

 

这项工作的主要贡献是“逆自递归流”(Inverse Autoregressive Flow,IAF),这种方法使 rich approximate posterior 能够并行计算,从而高度灵活,可以达到近乎随机的任意性。

 

我们在下面的图中展示了一些 32*32 的图像样本。前一幅是来自 DRAW 模型的早期样本(初级 VAE 样本看起来更差和模糊)。DRAW 模型一年前才发表的,由此也可以感受到训练生成模型的发展迅速。

 

[左]用 IAF 训练 VAE 生成的图像;[右]DRAW 模型生成的图像

 

3. InfoGAN

 

Peter Chen 等人提出了 InfoGAN ——GAN 的扩展。普通的 GAN 通过在模型里重新生成数据分布,让模型学会图像的disentangled 和 interpretable 表征。但是,其 layout 和 organization 是 underspecified。

 

InfoGAN 引入了额外的结构,得到了相当出色的结果。在三维人脸图像中,改变代码的一个连续维度,保持其他维度不变,很明显从每张图片给出的 5 行例子中,代码的 resulting dimension 是可解释的,模型在事先不知道摄像头角度、面部变化等特征存在的前提下,可能已经理解这些特征是存在的,并且十分重要:

 

(a)pose                    (b)Elevation

 

(c)Lighting             (d)Wide or Narrow

 

同时,值得一提的是,上述方法是非监督学习的方法。 因此,相比通过监督学习的方法实现了同样结果的思路,这种方法体现出了更高的水平。

 

3. 生成模型的深度强化学习(两项)

 

下面是两个强化学习场景下(另一个 OpenAI 聚焦的领域),生成式模型的完善:Curiosity-driven Exploration in Deep Reinforcement Learning via Bayesian Neural Networks。

 

在高维度连续空间中进行高效的探索是当前强化学习尚未解决的一个难题。没有有效的探索方法,智能体只能到处乱闯直到碰巧遇到奖励。若要对高维行动空间进行探索(比如机器人),这些算法是完全不够的。这篇论文中,Rein Houthooft 等人提出了 VIME,一个使用生成模型对不确定性进行探索的实用方法。

 

VIME 让智能体本身驱动;它主动地寻求意外的状态-行动。作者展示了 VIME 可以提高一系列策略搜索方法,并在更多稀疏奖励的实际任务(比如智能体需要在无指导的情形下学习原始行动的场景)取得了显著改进。

 

用 VIME 训练的策略

 

没有受训的策略

 

 

4. 生成对抗模仿学习

 

Jonathan Ho 等人提出了一个新的模仿学习(imitation learning)方法。Jonathan Ho 在斯坦福大学完成了这项工作的主要内容,他作为暑期实习生加入 OpenAI 后,结合 GAN 以及 RL 等相关工作的启发,最终完成了生成对抗模仿学习及代码。

 

标准的强化学习场景通常需要设计一个规定智能体预期行为的奖励函数。但实际情况是,有样做有时候会为了实现细节上的正确,而引入代价过高的试错过程。相较而言,模仿学习中,智能体从样本展示中学习,就免去了对奖励函数的依赖。

 

 

常用模仿方法包含两个阶段的流程:首先学习奖励函数,然后依照奖励函数执行深度强化学习。这样的过程非常缓慢,也由于这种间接性方法,很难保证结果策略的质量。这项工作展示了如何通过 GAN 直接从数据中抽取策略。这个方法在 OpenAI Gym 环境中可以根据专家表现进行策略学习。

 

 

 

 

展望未来

 

生成模型是快速发展的研究领域。在完善这些模型,扩展训练和数据集的同时,我们完全可以认为最终将会产生能够以假乱真的图像或视频样本。这可以用很多应用, 图像降噪(image denoising)、inpainting、高清分辨率(super-resolution)、结构化预测(structured prediction)、强化学习探索(exploration in reinforcement learning),以及神经网络预处理这些为数据打标签的很复杂、造价很高的领域,有很多潜力。

 

 

这项工作更深的启示是,在训练生成模型的过程中,我们最终会增进计算机对世界及其构成的理解。

一文学会用 Tensorflow 搭建神经网络

http://www.jianshu.com/p/e112012a4b2d

cs224d-Day 6: 快速入门 Tensorflow

本文是学习这个视频课程系列的笔记,课程链接是 youtube 上的,
讲的很好,浅显易懂,入门首选, 而且在github有代码,
想看视频的也可以去他的优酷里的频道找。

Tensorflow 官网


神经网络是一种数学模型,是存在于计算机的神经系统,由大量的神经元相连接并进行计算,在外界信息的基础上,改变内部的结构,常用来对输入和输出间复杂的关系进行建模。

神经网络由大量的节点和之间的联系构成,负责传递信息和加工信息,神经元也可以通过训练而被强化。

这个图就是一个神经网络系统,它由很多层构成。输入层就是负责接收信息,比如说一只猫的图片。输出层就是计算机对这个输入信息的认知,它是不是猫。隐藏层就是对输入信息的加工处理。

神经网络是如何被训练的,首先它需要很多数据。比如他要判断一张图片是不是猫。就要输入上千万张的带有标签的猫猫狗狗的图片,然后再训练上千万次。

神经网络训练的结果有对的也有错的,如果是错误的结果,将被当做非常宝贵的经验,那么是如何从经验中学习的呢?就是对比正确答案和错误答案之间的区别,然后把这个区别反向的传递回去,对每个相应的神经元进行一点点的改变。那么下一次在训练的时候就可以用已经改进一点点的神经元去得到稍微准确一点的结果。

神经网络是如何训练的呢?每个神经元都有属于它的激活函数,用这些函数给计算机一个刺激行为。

在第一次给计算机看猫的图片的时候,只有部分的神经元被激活,被激活的神经元所传递的信息是对输出结果最有价值的信息。如果输出的结果被判定为是狗,也就是说是错误的了,那么就会修改神经元,一些容易被激活的神经元会变得迟钝,另外一些神经元会变得敏感。这样一次次的训练下去,所有神经元的参数都在被改变,它们变得对真正重要的信息更为敏感。

Tensorflow 是谷歌开发的深度学习系统,用它可以很快速地入门神经网络。

它可以做分类,也可以做拟合问题,就是要把这个模式给模拟出来。

这是一个基本的神经网络的结构,有输入层,隐藏层,和输出层。
每一层点开都有它相应的内容,函数和功能。

那我们要做的就是要建立一个这样的结构,然后把数据喂进去。
把数据放进去后它就可以自己运行,TensorFlow 翻译过来就是向量在里面飞。

这个动图的解释就是,在输入层输入数据,然后数据飞到隐藏层飞到输出层,用梯度下降处理,梯度下降会对几个参数进行更新和完善,更新后的参数再次跑到隐藏层去学习,这样一直循环直到结果收敛。

tensors_flowing.gif

今天一口气把整个系列都学完了,先来一段完整的代码,然后解释重要的知识点!


1. 搭建神经网络基本流程

定义添加神经层的函数

1.训练的数据
2.定义节点准备接收数据
3.定义神经层:隐藏层和预测层
4.定义 loss 表达式
5.选择 optimizer 使 loss 达到最小

然后对所有变量进行初始化,通过 sess.run optimizer,迭代 1000 次进行学习:

import tensorflow as tf
import numpy as np

# 添加层
def add_layer(inputs, in_size, out_size, activation_function=None):
    # add one more layer and return the output of this layer
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

# 1.训练的数据
# Make up some real data 
x_data = np.linspace(-1,1,300)[:, np.newaxis]
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) - 0.5 + noise

# 2.定义节点准备接收数据
# define placeholder for inputs to network  
xs = tf.placeholder(tf.float32, [None, 1])
ys = tf.placeholder(tf.float32, [None, 1])

# 3.定义神经层:隐藏层和预测层
# add hidden layer 输入值是 xs,在隐藏层有 10 个神经元   
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
# add output layer 输入值是隐藏层 l1,在预测层输出 1 个结果
prediction = add_layer(l1, 10, 1, activation_function=None)

# 4.定义 loss 表达式
# the error between prediciton and real data    
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
                     reduction_indices=[1]))

# 5.选择 optimizer 使 loss 达到最小                   
# 这一行定义了用什么方式去减少 loss,学习率是 0.1       
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)


# important step 对所有变量进行初始化
init = tf.initialize_all_variables()
sess = tf.Session()
# 上面定义的都没有运算,直到 sess.run 才会开始运算
sess.run(init)

# 迭代 1000 次学习,sess.run optimizer
for i in range(1000):
    # training train_step 和 loss 都是由 placeholder 定义的运算,所以这里要用 feed 传入参数
    sess.run(train_step, feed_dict={xs: x_data, ys: y_data})
    if i % 50 == 0:
        # to see the step improvement
        print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))

2. 主要步骤的解释:

  • 之前写过一篇文章 TensorFlow 入门 讲了 tensorflow 的安装,这里使用时直接导入:
import tensorflow as tf
import numpy as np
  • 导入或者随机定义训练的数据 x 和 y:
x_data = np.random.rand(100).astype(np.float32)
y_data = x_data*0.1 + 0.3
  • 先定义出参数 Weights,biases,拟合公式 y,误差公式 loss:
Weights = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
biases = tf.Variable(tf.zeros([1]))
y = Weights*x_data + biases
loss = tf.reduce_mean(tf.square(y-y_data))
  • 选择 Gradient Descent 这个最基本的 Optimizer:
optimizer = tf.train.GradientDescentOptimizer(0.5)
  • 神经网络的 key idea,就是让 loss 达到最小:
train = optimizer.minimize(loss)
  • 前面是定义,在运行模型前先要初始化所有变量:
init = tf.initialize_all_variables()
  • 接下来把结构激活,sesseion像一个指针指向要处理的地方:
sess = tf.Session()
  • init 就被激活了,不要忘记激活:
sess.run(init)
  • 训练201步:
for step in range(201):
  • 要训练 train,也就是 optimizer:
sess.run(train)
  • 每 20 步打印一下结果,sess.run 指向 Weights,biases 并被输出:
if step % 20 == 0:
print(step, sess.run(Weights), sess.run(biases))

所以关键的就是 y,loss,optimizer 是如何定义的。


3. TensorFlow 基本概念及代码:

TensorFlow 入门 也提到了几个基本概念,这里是几个常见的用法。

  • Session

矩阵乘法:tf.matmul

product = tf.matmul(matrix1, matrix2) # matrix multiply np.dot(m1, m2)

定义 Session,它是个对象,注意大写:

sess = tf.Session()

result 要去 sess.run 那里取结果:

result = sess.run(product)
  • Variable

用 tf.Variable 定义变量,与python不同的是,必须先定义它是一个变量,它才是一个变量,初始值为0,还可以给它一个名字 counter:

state = tf.Variable(0, name='counter')

将 new_value 加载到 state 上,counter就被更新:

update = tf.assign(state, new_value)

如果有变量就一定要做初始化:

init = tf.initialize_all_variables() # must have if define variable
  • placeholder:

要给节点输入数据时用 placeholder,在 TensorFlow 中用placeholder 来描述等待输入的节点,只需要指定类型即可,然后在执行节点的时候用一个字典来“喂”这些节点。相当于先把变量 hold 住,然后每次从外部传入data,注意 placeholder 和 feed_dict 是绑定用的。

这里简单提一下 feed 机制, 给 feed 提供数据,作为 run()
调用的参数, feed 只在调用它的方法内有效, 方法结束, feed 就会消失。

import tensorflow as tf

input1 = tf.placeholder(tf.float32)
input2 = tf.placeholder(tf.float32)
ouput = tf.mul(input1, input2)

with tf.Session() as sess:
  print(sess.run(ouput, feed_dict={input1: [7.], input2: [2.]}))

4. 神经网络基本概念

  • 激励函数:

例如一个神经元对猫的眼睛敏感,那当它看到猫的眼睛的时候,就被激励了,相应的参数就会被调优,它的贡献就会越大。

下面是几种常见的激活函数:
x轴表示传递过来的值,y轴表示它传递出去的值:

激励函数在预测层,判断哪些值要被送到预测结果那里:

TensorFlow 常用的 activation function

  • 添加神经层:

输入参数有 inputs, in_size, out_size, 和 activation_function

import tensorflow as tf

def add_layer(inputs, in_size, out_size,  activation_function=None):

  Weights = tf.Variable(tf.random_normal([in_size, out_size]))
  biases = tf.Variable(tf.zeros([1, out_size]) + 0.1)
  Wx_plus_b = tf.matmul(inputs, Weights) + biases

  if activation_function is None:
    outputs = Wx_plus_b
  else:
    outputs = activation_function(Wx_plus_b)

return outputs
  • 分类问题的 loss 函数 cross_entropy :
# the error between prediction and real data
# loss 函数用 cross entropy
cross_entropy = tf.reduce_mean(-tf.reduce_sum(ys * tf.log(prediction),
                                              reduction_indices=[1]))       # loss
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
  • overfitting:

下面第三个图就是 overfitting,就是过度准确地拟合了历史数据,而对新数据预测时就会有很大误差:

Tensorflow 有一个很好的工具, 叫做dropout, 只需要给予它一个不被 drop 掉的百分比,就能很好地降低 overfitting。

dropout 是指在深度学习网络的训练过程中,按照一定的概率将一部分神经网络单元暂时从网络中丢弃,相当于从原始的网络中找到一个更瘦的网络,这篇博客中讲的非常详细

代码实现就是在 add layer 函数里加上 dropout, keep_prob 就是保持多少不被 drop,在迭代时在 sess.run 中被 feed:

def add_layer(inputs, in_size, out_size, layer_name, activation_function=None, ):
    # add one more layer and return the output of this layer
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, )
    Wx_plus_b = tf.matmul(inputs, Weights) + biases

    # here to dropout
    # 在 Wx_plus_b 上drop掉一定比例
    # keep_prob 保持多少不被drop,在迭代时在 sess.run 中 feed
    Wx_plus_b = tf.nn.dropout(Wx_plus_b, keep_prob)

    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b, )
    tf.histogram_summary(layer_name + '/outputs', outputs)  
    return outputs

5. 可视化 Tensorboard

Tensorflow 自带 tensorboard ,可以自动显示我们所建造的神经网络流程图:

就是用 with tf.name_scope 定义各个框架,注意看代码注释中的区别:

import tensorflow as tf


def add_layer(inputs, in_size, out_size, activation_function=None):
    # add one more layer and return the output of this layer
    # 区别:大框架,定义层 layer,里面有 小部件
    with tf.name_scope('layer'):
        # 区别:小部件
        with tf.name_scope('weights'):
            Weights = tf.Variable(tf.random_normal([in_size, out_size]), name='W')
        with tf.name_scope('biases'):
            biases = tf.Variable(tf.zeros([1, out_size]) + 0.1, name='b')
        with tf.name_scope('Wx_plus_b'):
            Wx_plus_b = tf.add(tf.matmul(inputs, Weights), biases)
        if activation_function is None:
            outputs = Wx_plus_b
        else:
            outputs = activation_function(Wx_plus_b, )
        return outputs


# define placeholder for inputs to network
# 区别:大框架,里面有 inputs x,y
with tf.name_scope('inputs'):
    xs = tf.placeholder(tf.float32, [None, 1], name='x_input')
    ys = tf.placeholder(tf.float32, [None, 1], name='y_input')

# add hidden layer
l1 = add_layer(xs, 1, 10, activation_function=tf.nn.relu)
# add output layer
prediction = add_layer(l1, 10, 1, activation_function=None)

# the error between prediciton and real data
# 区别:定义框架 loss
with tf.name_scope('loss'):
    loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction),
                                        reduction_indices=[1]))

# 区别:定义框架 train
with tf.name_scope('train'):
    train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)

sess = tf.Session()

# 区别:sess.graph 把所有框架加载到一个文件中放到文件夹"logs/"里 
# 接着打开terminal,进入你存放的文件夹地址上一层,运行命令 tensorboard --logdir='logs/'
# 会返回一个地址,然后用浏览器打开这个地址,在 graph 标签栏下打开
writer = tf.train.SummaryWriter("logs/", sess.graph)
# important step
sess.run(tf.initialize_all_variables())

运行完上面代码后,打开 terminal,进入你存放的文件夹地址上一层,运行命令 tensorboard –logdir=’logs/’ 后会返回一个地址,然后用浏览器打开这个地址,点击 graph 标签栏下就可以看到流程图了:


6. 保存和加载

训练好了一个神经网络后,可以保存起来下次使用时再次加载:

import tensorflow as tf
import numpy as np

## Save to file
# remember to define the same dtype and shape when restore
W = tf.Variable([[1,2,3],[3,4,5]], dtype=tf.float32, name='weights')
b = tf.Variable([[1,2,3]], dtype=tf.float32, name='biases')

init= tf.initialize_all_variables()

saver = tf.train.Saver()

# 用 saver 将所有的 variable 保存到定义的路径
with tf.Session() as sess:
   sess.run(init)
   save_path = saver.save(sess, "my_net/save_net.ckpt")
   print("Save to path: ", save_path)


################################################

# restore variables
# redefine the same shape and same type for your variables
W = tf.Variable(np.arange(6).reshape((2, 3)), dtype=tf.float32, name="weights")
b = tf.Variable(np.arange(3).reshape((1, 3)), dtype=tf.float32, name="biases")

# not need init step

saver = tf.train.Saver()
# 用 saver 从路径中将 save_net.ckpt 保存的 W 和 b restore 进来
with tf.Session() as sess:
    saver.restore(sess, "my_net/save_net.ckpt")
    print("weights:", sess.run(W))
    print("biases:", sess.run(b))

tensorflow 现在只能保存 variables,还不能保存整个神经网络的框架,所以再使用的时候,需要重新定义框架,然后把 variables 放进去学习。

 

文/不会停的蜗牛(简书作者)
原文链接:http://www.jianshu.com/p/e112012a4b2d
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

TensorFlow 入门

http://www.jianshu.com/p/6766fbcd43b9

CS224d-Day 2:

在 Day 1 里,先了解了一下 NLP 和 DP 的主要概念,对它们有了一个大体的印象,用向量去表示研究对象,用神经网络去学习,用 TensorFlow 去训练模型,基本的模型和算法包括 word2vec,softmax,RNN,LSTM,GRU,CNN,大型数据的 seq2seq,还有未来比较火热的研究方向 DMN,还有模型的调优。

今天先不直接进入理论学习,而是先学习一下 TensorFlow,在原课程里,这部分在第7讲,但是我觉得最高效地学习算法的方式,就是一边学理论,一边写代码,实践中才能理解更深刻。

Day 2 先认识 TensorFlow,了解一下基本用法,下一次就写代码来训练模型算法,以问题为导向,以项目为驱动。


本文结构:

  • 1. TensorFlow 是什么
  • 2. 为什么需要 TensorFlow
  • 3. TensorFlow 的优点
  • 4. TensorFlow 的工作原理
  • 5. 安装
  • 6. TensorFlow 基本用法
    • 要点
    • 例子
    • 概念
      • 张量
      • 会话

1. TensorFlow 是什么

是一个深度学习库,由 Google 开源,可以对定义在 Tensor(张量)上的函数自动求导。

Tensor(张量)意味着 N 维数组,Flow(流)意味着基于数据流图的计算,TensorFlow即为张量从图的一端流动到另一端。

它的一大亮点是支持异构设备分布式计算,它能够在各个平台上自动运行模型,从电话、单个CPU / GPU到成百上千GPU卡组成的分布式系统。

支持CNN、RNN和LSTM算法,是目前在 Image,NLP 最流行的深度神经网络模型。


2. 为什么需要 TensorFlow 等库

深度学习通常意味着建立具有很多层的大规模的神经网络。

除了输入X,函数还使用一系列参数,其中包括标量值、向量以及最昂贵的矩阵和高阶张量。

在训练网络之前,需要定义一个代价函数,常见的代价函数包括回归问题的方差以及分类时候的交叉熵。

训练时,需要连续的将多批新输入投入网络,对所有的参数求导后,代入代价函数,从而更新整个网络模型。

这个过程中有两个主要的问题:1. 较大的数字或者张量在一起相乘百万次的处理,使得整个模型代价非常大。2. 手动求导耗时非常久。

所以 TensorFlow 的对函数自动求导以及分布式计算,可以帮我们节省很多时间来训练模型。


3. TensorFlow 的优点

第一,基于Python,写的很快并且具有可读性。

第二,在多GPU系统上的运行更为顺畅。

第三,代码编译效率较高。

第四,社区发展的非常迅速并且活跃。

第五,能够生成显示网络拓扑结构和性能的可视化图。


4. TensorFlow 的工作原理

TensorFlow是用数据流图(data flow graphs)技术来进行数值计算的。

数据流图是描述有向图中的数值计算过程。

有向图中,节点通常代表数学运算,边表示节点之间的某种联系,它负责传输多维数据(Tensors)。

节点可以被分配到多个计算设备上,可以异步和并行地执行操作。因为是有向图,所以只有等到之前的入度节点们的计算状态完成后,当前节点才能执行操作。


5. 安装

极客学院有官方文档翻译版,讲的很清楚,有各种安装方式的讲解。

我选择基于 Anaconda 的安装,因为这个很方便。

Anaconda 是一个集成许多第三方科学计算库的 Python 科学计算环境,用 conda 作为自己的包管理工具,同时具有自己的计算环境,类似 Virtualenv。

  • 安装 Anaconda
    我之前已经安装过 Anaconda 了,直接从下面进行:
  • 建立一个 conda 计算环境
# 计算环境名字叫 tensorflow:
# Python 2.7
$ conda create -n tensorflow python=2.7
  • 激活环境,使用 conda 安装 TensorFlow
$ source activate tensorflow
(tensorflow)$  # Your prompt should change

# Mac OS X, CPU only:
(tensorflow)$ pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.8.0rc0-py2-none-any.whl
  • 安装成功后,每次使用 TensorFlow 的时候需要激活 conda 环境
  • conda 环境激活后,你可以测试是否成功,在终端进入 python,输入下面代码,没有提示错误,说明安装 TensorFlow 成功:
$ python
...
>>> import tensorflow as tf
>>> hello = tf.constant('Hello, TensorFlow!')
>>> sess = tf.Session()
>>> print(sess.run(hello))
Hello, TensorFlow!
>>> a = tf.constant(10)
>>> b = tf.constant(32)
>>> print(sess.run(a + b))
42
>>>
  • 当你不用 TensorFlow 的时候,关闭环境:
(tensorflow)$ source deactivate

$  # Your prompt should change back
  • 再次使用的时候再激活:
$ source activate tensorflow
(tensorflow)$  # Run Python programs that use TensorFlow.
...

(tensorflow)$ source deactivate

在 Jupyter notebook 里用 TensorFlow
我在 (tensorflow)$ 直接输入 jupyter notebook 后,输入 import tensorflow as tf 是有错误的,可以参考这里


6. TensorFlow 基本用法

接下来按照官方文档中的具体代码,来看一下基本用法。

你需要理解在TensorFlow中,是如何:

  • 将计算流程表示成图;
  • 通过Sessions来执行图计算;
  • 将数据表示为tensors;
  • 使用Variables来保持状态信息;
  • 分别使用feeds和fetches来填充数据和抓取任意的操作结果;

先看个栗子:
例1,生成三维数据,然后用一个平面拟合它:

# (tensorflow)$ python   用 Python API 写 TensorFlow 示例代码

import tensorflow as tf
import numpy as np

# 用 NumPy 随机生成 100 个数据
x_data = np.float32(np.random.rand(2, 100)) 
y_data = np.dot([0.100, 0.200], x_data) + 0.300

# 构造一个线性模型
b = tf.Variable(tf.zeros([1]))
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b

# 最小化方差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# 初始化变量
init = tf.initialize_all_variables()

# 启动图 (graph)
sess = tf.Session()
sess.run(init)

# 拟合平面
for step in xrange(0, 201):
    sess.run(train)
    if step % 20 == 0:
        print step, sess.run(W), sess.run(b)

# 输出结果为:
0 [[-0.14751725  0.75113136]] [ 0.2857058]
20 [[ 0.06342752  0.32736415]] [ 0.24482927]
40 [[ 0.10146417  0.23744738]] [ 0.27712563]
60 [[ 0.10354312  0.21220125]] [ 0.290878]
80 [[ 0.10193551  0.20427427]] [ 0.2964265]
100 [[ 0.10085492  0.201565  ]] [ 0.298612]
120 [[ 0.10035028  0.20058727]] [ 0.29946309]
140 [[ 0.10013894  0.20022322]] [ 0.29979277]
160 [[ 0.1000543   0.20008542]] [ 0.29992008]
180 [[ 0.10002106  0.20003279]] [ 0.29996923]
200 [[ 0.10000814  0.20001261]] [ 0.29998815]

注意这几条代码:

W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))

y = tf.matmul(W, x_data) + b

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

sess.run(train) 
print step, sess.run(W), sess.run(b)

接下来看具体概念:

  • TensorFlow 用图来表示计算任务,图中的节点被称之为operation,缩写成op。
  • 一个节点获得 0 个或者多个张量 tensor,执行计算,产生0个或多个张量。
  • 图必须在会话(Session)里被启动,会话(Session)将图的op分发到CPU或GPU之类的设备上,同时提供执行op的方法,这些方法执行后,将产生的张量(tensor)返回。

1. 构建图
例2,计算矩阵相乘:

import tensorflow as tf

# 创建一个 常量 op, 返回值 'matrix1' 代表这个 1x2 矩阵.
matrix1 = tf.constant([[3., 3.]])

# 创建另外一个 常量 op, 返回值 'matrix2' 代表这个 2x1 矩阵.
matrix2 = tf.constant([[2.],[2.]])

# 创建一个矩阵乘法 matmul op , 把 'matrix1''matrix2' 作为输入.
# 返回值 'product' 代表矩阵乘法的结果.
product = tf.matmul(matrix1, matrix2)

默认图有三个节点, 两个 constant() op, 和一个 matmul() op. 为了真正进行矩阵相乘运算, 并得到矩阵乘法的结果, 你必须在会话里启动这个图.

2. 张量 Tensor
从向量空间到实数域的多重线性映射(multilinear maps)(v是向量空间,v*是对偶空间)
例如代码中的 [[3., 3.]],Tensor 可以看作是一个 n 维的数组或列表。在 TensorFlow 中用 tensor 数据结构来代表所有的数据, 计算图中, 操作间传递的数据都是 tensor。

3. 在一个会话中启动图
创建一个 Session 对象, 如果无任何创建参数, 会话构造器将启动默认图。
会话负责传递 op 所需的全部输入,op 通常是并发执行的。

# 启动默认图.
sess = tf.Session()

# 调用 sess 的 'run()' 方法, 传入 'product' 作为该方法的参数,
# 触发了图中三个 op (两个常量 op 和一个矩阵乘法 op),
# 向方法表明, 我们希望取回矩阵乘法 op 的输出.
result = sess.run(product)

# 返回值 'result' 是一个 numpy `ndarray` 对象.
print result
# ==> [[ 12.]]

# 任务完成, 需要关闭会话以释放资源。
sess.close()

交互式使用
在 Python API 中,使用一个会话 Session 来 启动图, 并调用 Session.run() 方法执行操作.

为了便于在 IPython 等交互环境使用 TensorFlow,需要用 InteractiveSession 代替 Session 类, 使用 Tensor.eval() 和 Operation.run() 方法代替 Session.run()。

例3,计算 ‘x’ 减去 ‘a’:

# 进入一个交互式 TensorFlow 会话.
import tensorflow as tf
sess = tf.InteractiveSession()

x = tf.Variable([1.0, 2.0])
a = tf.constant([3.0, 3.0])

# 使用初始化器 initializer op 的 run() 方法初始化 'x' 
x.initializer.run()

# 增加一个减法 sub op, 从 'x' 减去 'a'. 运行减法 op, 输出结果 
sub = tf.sub(x, a)
print sub.eval()
# ==> [-2. -1.]

变量 Variable

上面用到的张量是常值张量(constant)。

变量 Variable,是维护图执行过程中的状态信息的. 需要它来保持和更新参数值,是需要动态调整的。

下面代码中有 tf.initialize_all_variables,是预先对变量初始化,
Tensorflow 的变量必须先初始化,然后才有值!而常值张量是不需要的。

下面的 assign() 操作和 add() 操作,在调用 run() 之前, 它并不会真正执行赋值和加和操作。

例4,使用变量实现一个简单的计数器:

# -创建一个变量, 初始化为标量 0.  初始化定义初值
state = tf.Variable(0, name="counter")

# 创建一个 op, 其作用是使 state 增加 1
one = tf.constant(1)
new_value = tf.add(state, one)
update = tf.assign(state, new_value)

# 启动图后, 变量必须先经过`初始化` (init) op 初始化,
# 才真正通过Tensorflow的initialize_all_variables对这些变量赋初值
init_op = tf.initialize_all_variables()

# 启动默认图, 运行 op
with tf.Session() as sess:

  # 运行 'init' op
  sess.run(init_op)

  # 打印 'state' 的初始值
  # 取回操作的输出内容, 可以在使用 Session 对象的 run() 调用 执行图时, 
  # 传入一些 tensor, 这些 tensor 会帮助你取回结果. 
  # 此处只取回了单个节点 state,
  # 也可以在运行一次 op 时一起取回多个 tensor: 
  # result = sess.run([mul, intermed])
  print sess.run(state)

  # 运行 op, 更新 'state', 并打印 'state'
  for _ in range(3):
    sess.run(update)
    print sess.run(state)

# 输出:

# 0
# 1
# 2
# 3

上面的代码定义了一个如下的计算图:

Ok,总结一下,来一个清晰的代码:
过程就是:建图->启动图->运行取值

计算矩阵相乘:

import tensorflow as tf

# 建图
matrix1 = tf.constant([[3., 3.]])
matrix2 = tf.constant([[2.],[2.]])

product = tf.matmul(matrix1, matrix2)

# 启动图
sess = tf.Session()

# 取值
result = sess.run(product)
print result

sess.close()

上面的几个代码介绍了基本用法,通过观察,有没有觉得 tf 和 numpy 有点像呢。

TensorFlow和普通的Numpy的对比
cs224d的课件中有下面这个代码,来看一下二者之间的区别:

eval()

在 Python 中定义完 a 后,直接打印就可以看到 a。

In [37]: a = np.zeros((2,2))

In [39]: print(a)
[[ 0.  0.]
 [ 0.  0.]]

但是在 Tensorflow 中需要显式地输出(evaluation,也就是说借助eval()函数)!

In [38]: ta = tf.zeros((2,2))

In [40]: print(ta)
Tensor("zeros_1:0", shape=(2, 2), dtype=float32)

In [41]: print(ta.eval())
[[ 0.  0.]
[ 0. 0.]]

通过几个例子了解了基本的用法,feed 在上面的例子中还没有写到,下一次就能用到了,其他的可以查询这里


Day 1 宏观了解了 NLP,Day 2 搞定了工具,下次要直接先进入实战,训练模型,先从 Logistic 和 NN 开始,一边看模型一边写代码一边思考模型原理,这样理解才会更深刻!

 

文/不会停的蜗牛(简书作者)
原文链接:http://www.jianshu.com/p/6766fbcd43b9
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

解析 DeepMind 深度强化学习 (Deep Reinforcement Learning) 技术

文/Not_GOD(简书作者)
原文链接:http://www.jianshu.com/p/d347bb2ca53c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

Two years ago, a small company in London called DeepMind uploaded their pioneering paper “Playing Atari with Deep Reinforcement Learning” to Arxiv. In this paper they demonstrated how a computer learned to play Atari 2600 video games by observing just the screen pixels and receiving a reward when the game score increased. The result was remarkable, because the games and the goals in every game were very different and designed to be challenging for humans. The same model architecture, without any change, was used to learn seven different games, and in three of them the algorithm performed even better than a human!

It has been hailed since then as the first step towards general artificial intelligence – an AI that can survive in a variety of environments, instead of being confined to strict realms such as playing chess. No wonder DeepMind was immediately bought by Google and has been on the forefront of deep learning research ever since. In February 2015 their paper “Human-level control through deep reinforcement learning” was featured on the cover of Nature, one of the most prestigious journals in science. In this paper they applied the same model to 49 different games and achieved superhuman performance in half of them.

Still, while deep models for supervised and unsupervised learning have seen widespread adoption in the community, deep reinforcement learning has remained a bit of a mystery. In this blog post I will be trying to demystify this technique and understand the rationale behind it. The intended audience is someone who already has background in machine learning and possibly in neural networks, but hasn’t had time to delve into reinforcement learning yet.

我们按照下面的几个问题来看看到底深度强化学习技术长成什么样?

  1. 什么是强化学习的主要挑战?针对这个问题,我们会讨论 credit assignment 问题和 exploration-exploitation 困境。
  2. 如何使用数学来形式化强化学习?我们会定义 Markov Decision Process 并用它来对强化学习进行分析推理。
  3. 我们如何指定长期的策略?这里,定义了 discounted future reward,这也给出了在下面部分的算法的基础。
  4. 如何估计或者近似未来收益?给出了简单的基于表的 Q-learning 算法的定义和分析。
  5. 如果状态空间非常巨大该怎么办?这里的 Q-table 就可以使用(深度)神经网络来替代。
  6. 怎么样将这个模型真正可行?采用 Experience replay 技术来稳定神经网络的学习。
  7. 这已经足够了么?最后会研究一些对 exploration-exploitation 问题的简单解决方案。

强化学习

Consider the game Breakout. In this game you control a paddle at the bottom of the screen and have to bounce the ball back to clear all the bricks in the upper half of the screen. Each time you hit a brick, it disappears and your score increases – you get a reward.

图 1:Atari Breakout 游戏:来自 DeepMind

Suppose you want to teach a neural network to play this game. Input to your network would be screen images, and output would be three actions: left, right or fire (to launch the ball). It would make sense to treat it as a classification problem – for each game screen you have to decide, whether you should move left, right or press fire. Sounds straightforward? Sure, but then you need training examples, and a lots of them. Of course you could go and record game sessions using expert players, but that’s not really how we learn. We don’t need somebody to tell us a million times which move to choose at each screen. We just need occasional feedback that we did the right thing and can then figure out everything else ourselves.
This is the task reinforcement learning tries to solve. Reinforcement learning lies somewhere in between supervised and unsupervised learning. Whereas in supervised learning one has a target label for each training example and in unsupervised learning one has no labels at all, in reinforcement learning one has sparse and time-delayed labels – the rewards. 基于这些收益,agent 必须学会在环境中如何行动。

尽管这个想法非常符合直觉,但是实际操作时却困难重重。例如,当你击中一个砖块,并得到收益时,这常常和最近做出的行动(paddle 的移动)没有关系。在你将 paddle 移动到了正确的位置时就可以将球弹回,其实所有的困难的工作已经完成。这个问题被称作是 credit assignment 问题——先前的行动会影响到当前的收益的获得与否及收益的总量。

一旦你想出来一个策略来收集一定数量的收益,你是要固定在当前的策略上还是尝试其他的策略来得到可能更好的策略呢?在上面的 Breakout 游戏中,简单的策略就是移动到最左边的等在那里。发出球球时,球更可能是向左飞去,这样你能够轻易地在死前获得 10 分。但是,你真的满足于做到这个程度么? 这就是 exploration-exploit 困境 ——你应当利用已有的策略还是去探索其他的可能更好的策略。

强化学习是关于人类(或者更一般的动物)学习的重要模型。我们受到来自父母、分数、薪水的奖赏都是收益的各类例子。credit assignment 问题exploration-exploitation 困境 在商业和人际关系中常常出现。这也是研究强化学习及那些提供尝试新的观点的沙盒的博弈游戏的重要原因。

Markov Decision Process

现在的问题就是,如何来形式化这个强化学习问题使得我们可以对其进行分析推理。目前最常见的就是将其表示成一个 Markov decision process。

假设你是一个 agent,在一个环境中(比如说 Breakout 游戏)。环境会处在某个状态下(比如说,paddle 的位置、球的位置和方向、每个砖块是否存在等等)。agent 可以在环境中执行某种行动(比如说,将 paddle 向左或者向右移动)。这些行动有时候会带来收益(比如说分数的增加)。行动会改变环境并使其新的状态,然后 agent 又可以这行另外的行动,如此进行下去。如何选择这些行动的规则称为策略。一般来说环境是随机的,这意味着下一个状态的出现在某种程度上是随机的(例如,你输了一个球的时候,重新启动新球,这个时候的射出方向是随机选定的)。

图 2:左:强化学习问题。右:Markov decision process

状态和行动的集合,以及从一个状态跳转到另一个状态的规则,共同真诚了 Markov decision process。这个过程(比方说一次游戏过程)的一个 episode 形成了一个有限的状态、行动和收益的序列:

这里的 s_i 表示状态,a_i 表示行动,而 r_{i+1} 是在执行行动的汇报。episode 以 terminal 状态 s_n 结尾(可能就是“游戏结束”画面)。MDP 依赖于 Markov 假设——下一个状态 s_{i+1} 的概率仅仅依赖于当前的状态 s_i 和行动 a_i,但不依赖此前的状态和行动。

Discounted Future Reward

To perform well in the long-term, we need to take into account not only the immediate rewards, but also the future rewards we are going to get. How should we go about that?

Given one run of the Markov decision process, we can easily calculate the total reward for one episode:

Given that, the total future reward from time point t onward can be expressed as:

But because our environment is stochastic, we can never be sure, if we will get the same rewards the next time we perform the same actions. The more into the future we go, the more it may diverge. For that reason it is common to use discounted future reward instead:

Here γ is the discount factor between 0 and 1 – the more into the future the reward is, the less we take it into consideration. It is easy to see, that discounted future reward at time step t can be expressed in terms of the same thing at time step t+1:

If we set the discount factor γ=0, then our strategy will be short-sighted and we rely only on the immediate rewards. If we want to balance between immediate and future rewards, we should set discount factor to something like γ=0.9. If our environment is deterministic and the same actions always result in same rewards, then we can set discount factor γ=1.

A good strategy for an agent would be to always choose an action that maximizes the (discounted) future reward.

Q-learning

In Q-learning we define a function Q(s, a) representing the maximum discounted future reward when we perform action a in state s, and continue optimally from that point on.

**

**The way to think about Q(s, a) is that it is “the best possible score at the end of the game after performing action a in state s“. It is called Q-function, because it represents the “quality” of a certain action in a given state.

This may sound like quite a puzzling definition. How can we estimate the score at the end of game, if we know just the current state and action, and not the actions and rewards coming after that? We really can’t. But as a theoretical construct we can assume existence of such a function. Just close your eyes and repeat to yourself five times: “Q(s, a) exists, Q(s, a) exists, …”. Feel it?

If you’re still not convinced, then consider what the implications of having such a function would be. Suppose you are in state and pondering whether you should take action a or b. You want to select the action that results in the highest score at the end of game. Once you have the magical Q-function, the answer becomes really simple – pick the action with the highest Q-value!

Here π represents the policy, the rule how we choose an action in each state.

OK, how do we get that Q-function then? Let’s focus on just one transition <s, a, r, s’>. Just like with discounted future rewards in the previous section, we can express the Q-value of state s and action a in terms of the Q-value of the next state s’.

This is called the Bellman equation. If you think about it, it is quite logical – maximum future reward for this state and action is the immediate reward plus maximum future reward for the next state.

The main idea in Q-learning is that we can iteratively approximate the Q-function using the Bellman equation. In the simplest case the Q-function is implemented as a table, with states as rows and actions as columns. The gist of the Q-learning algorithm is as simple as the following[1]:

α in the algorithm is a learning rate that controls how much of the difference between previous Q-value and newly proposed Q-value is taken into account. In particular, when α=1, then two Q[s,a] cancel and the update is exactly the same as the Bellman equation.

The maxa’ Q[s’,a’] that we use to update Q[s,a] is only an approximation and in early stages of learning it may be completely wrong. However the approximation get more and more accurate with every iteration and it has been shown, that if we perform this update enough times, then the Q-function will converge and represent the true Q-value.

Deep Q Network

环境的状态可以用 paddle 的位置,球的位置和方向以及每个砖块是否消除来确定。不过这个直觉上的表示与游戏相关。我们能不能获得某种更加通用适合所有游戏的表示呢?最明显的选择就是屏幕像素——他们隐式地包含所有关于除了球的速度和方向外的游戏情形的相关信息。不过两个时间上相邻接的屏幕可以包含这两个丢失的信息。

如果我们像 DeepMind 的论文中那样处理游戏屏幕的话——获取四幅最后的屏幕画面,将他们重新规整为 84 X 84 的大小,转换为 256 灰度层级——我们会得到一个 256^{84X84X4} 大小的可能游戏状态。这意味着我们的 Q-table 中需要有 10^67970 行——这比已知的宇宙空间中的原子的数量还要大得多!可能有人会说,很多像素的组合(也就是状态)不会出现——这样其实可以使用一个稀疏的 table 来包含那些被访问到的状态。即使这样,很多的状态仍然是很少被访问到的,也许需要宇宙的生命这么长的时间让 Q-table 收敛。我们希望理想化的情形是有一个对那些还未遇见的状态的 Q-value 的猜测。

这里就是深度学习发挥作用的地方。神经网络其实对从高度结构化的数据中获取特征非常在行。我们可以用神经网络表示 Q-function,以状态(四幅屏幕画面)和行动作为输入,以对应的 Q-value 作为输出。另外,我们可以仅仅用游戏画面作为输入对每个可能的行动输出一个 Q-value。后面这个观点对于我们想要进行 Q-value 的更新或者选择最优的 Q-value 对应操作来说要更方便一些,这样我们仅仅需要进行一遍网络的前向传播就可立即得到所有行动的 Q-value。

图 3:左:DQN 的初级形式;右:DQN 的优化形式,用在 DeepMind 的论文中的版本

DeepMind 使用的深度神经网络架构如下:

这实际上是一个经典的卷积神经网络,包含 3 个卷积层加上 2 个全连接层。对图像识别的人们应该会注意到这里没有包含 pooling 层。但如果你好好想想这里的情况,你会明白,pooling 层会带来变换不变性 —— 网络会对图像中的对象的位置没有很强的感知。这个特性在诸如 ImageNet 这样的分类问题中会有用,但是在这里游戏的球的位置其实是潜在能够决定收益的关键因素,我们自然不希望失去这样的信息了!

网络的输入是 4 幅 84X84 的灰度屏幕画面。网络的输出是对每个可能的行动(在 Atari 中是 18 个)。Q-value 可能是任何实数,其实这是一个回归任务,我们可以通过简单的平方误差来进行优化。

给定转移 <s, a, r, s’>,Q-table 更新规则变动如下:

  1. 对当前的状态 s 执行前向传播,获得对所有行动的预测 Q-value
  2. 对下一状态 s’ 执行前向传播,计算网络输出最大操作:max_{a’} Q(s’, a’)
  3. 设置行动的 Q-value 目标值为 r + γ max_{a’} Q(s’, a’)。使用第二步的 max 值。对所有其他的行动,设置为和第一步返回结果相同的 Q-value 目标值,让这些输出的误差设置为 0
  4. 使用反向传播算法更新权重

Experience Replay

到现在,我们有了使用 Q-learning 如何估计未来回报和用卷积神经网络近似 Q-function 的方法。但是有个问题是,使用非线性函数来近似 Q-value 其实是非常不稳定的。对这个问题其实也有一堆技巧来让其收敛。不过这样也会花点时间,在单个 GPU 上估计要一个礼拜。

其中最为重要的技巧是 experience replay。在游戏过程中,所有的经验 <s, a, r’, s’> 都存放在一个 replay memory 中。训练网络时,replay memory 中随机的 minibatch 会取代最近的状态转移。这会将连续的训练样本之间的相似性打破,否则容易将网络导向一个局部最优点。同样 experience replay 让训练任务与通常的监督学习更加相似,这样也简化了程序的 debug 和算法的测试。当然我们实际上也是可以收集人类玩家的 experience 并用这些数据进行训练。

Exploration-Exploitation

Q-learning 试着解决 credit assignment 问题——将受益按时间传播,直到导致获得受益的实际的关键决策点为止。但是我们并没有解决 exploration-exploitation 困境……

首先我们注意到,当 Q-table 或者 Q-network 随机初始化时,其预测结果也是随机的。如果我们选择一个拥有最高的 Q-value 的行动,这个行动是随机的,这样 agent 会进行任性的“exploration”。当 Q-function 收敛时,它会返回一个更加一致的 Q-value 此时 exploration 的次数就下降了。所以我们可以说,Q-learning 将 exploration 引入了算法的一部分。但是这样的 exploration 是贪心的,它会采用找到的最有效的策略。

对上面问题的一个简单却有效的解决方案是 ε-greedy exploration——以概率ε选择一个随机行动,否则按照最高的 Q-value 进行贪心行动。在 DeepMind 的系统中,对ε本身根据时间进行的从 1 到 0.1 的下降,也就是说开始时系统完全进行随机的行动来最大化地 explore 状态空间,然后逐渐下降到一个固定的 exploration 的比例。

Deep Q-learning 算法

现在我们得到加入 experience replay的最终版本:

DeepMind 其实还使用了很多的技巧来让系统工作得更好——如 target network、error clipping、reward clipping 等等,这里我们不做介绍。

该算法最为有趣的一点就是它可以学习任何东西。你仔细想想——由于我们的 Q-function 是随机初始化的,刚开始给出的结果就完全是垃圾。然后我们就用这样的垃圾(下个状态的最高 Q-value)作为网络的目标,仅仅会偶然地引入微小的收益。这听起来非常疯狂,为什么它能够学习任何有意义的东西呢?然而,它确实如此神奇。

Final notes

Many improvements to deep Q-learning have been proposed since its first introduction – Double Q-learning, Prioritized Experience Replay, Dueling Network Architecture and extension to continuous action space to name a few. For latest advancements check out the NIPS 2015 deep reinforcement learning workshop and ICLR 2016 (search for “reinforcement” in title). But beware, that deep Q-learning has been patented by Google.

It is often said, that artificial intelligence is something we haven’t figured out yet. Once we know how it works, it doesn’t seem intelligent any more. But deep Q-networks still continue to amaze me. Watching them figure out a new game is like observing an animal in the wild – a rewarding experience by itself.

Credits

Thanks to Ardi Tampuu, Tanel Pärnamaa, Jaan Aru, Ilya Kuzovkin, Arjun Bansal and Urs Köster for comments and suggestions on the drafts of this post.

Links

David Silver’s lecture about deep reinforcement learning
Slightly awkward but accessible illustration of Q-learning
UC Berkley’s course on deep reinforcement learning
David Silver’s reinforcement learning course
Nando de Freitas’ course on machine learning (two lectures about reinforcement learning in the end)
Andrej Karpathy’s course on convolutional neural networks

[1] Algorithm adapted from http://artint.info/html/ArtInt_265.html

 

文/Not_GOD(简书作者)
原文链接:http://www.jianshu.com/p/d347bb2ca53c
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

循环神经网络---Recurrent Neural Networks

循环神经网络(Recurrent Neural Networks)是目前非常流行的神经网络模型,在自然语言处理的很多任务中已经展示出卓越的效果。但是在介绍 RNN 的诸多文章中,通常都是介绍 RNN 的使用方法和实战效果,很少有文章会介绍关于该神经网络的训练过程。

循环神经网络是一个在时间上传递的神经网络,网络的深度就是时间的长度。该神经网络是专门用来处理时间序列问题的,能够提取时间序列的信息。如果是前向神经网络,每一层的神经元信号只能够向下一层传播,样本的处理在时刻上是独立的。对于循环神经网络而言,神经元在这个时刻的输出可以直接影响下一个时间点的输入,因此该神经网络能够处理时间序列方面的问题。

本文将会从数学的角度展开关于循环神经网络的使用方法和训练过程,在本文中,会假定读者已经掌握数学分析中的导数偏导数链式法则梯度下降法等基础内容。本文将会使用传统的后向传播算法(Back Propagation)来训练 RNN 模型。

微信公众号文章循环神经网络

This slideshow requires JavaScript.

 

 

zr9558's Blog