亚马逊AWS官方博客

程序员的深度学习入门指南

本文根据费良宏在2016QCon全球软件开发大会(上海)上的演讲整理而成。

今天我想跟大家分享的话题与深度学习有关。事实上,深度学习本身是一个非常庞大的知识体系。今天的内容,不会涉及深度学习的理论知识,更多想从程序员的视角出发,让大家观察一下深度学习对我们程序员意味着什么,以及我们如何能够利用这样一个高速发展的学科,来帮助程序员提升软件开发的能力。

前言

1973年,美国上映了一部热门的科幻电影叫做《Westworld》,三年之后又有一个续集叫做《Futureworld》。这部电影在80年代初被引进到中国叫《未来世界》。那部电影对我来讲简直可以说得上是震撼。影片中出现了很多机器人,表情丰富的面部下面都是集成电路板。这让那时候的我觉得未来世界都是那么遥远、那么样的神秘。时间转到了2016年,很多朋友可能都在追看HBO斥巨资拍摄的同一个题材的系列剧《Westworld》。如果前两部电影还是局限在机器人、人工智能这样的话题,2016年的新剧则在剧情、以及对于人工智能的思考方面有了很大的突破。不再渲染机器人是否会威胁到人类,而是在探讨 “Dreams are mainly memories“这一类更具哲理的问题。记忆究竟如何影响了智能这个话题非常值得我们去思考,也给我们一个很好的启示 – 今天,人工智能领域究竟有了怎样的发展和进步。

今天我们探讨的话题不仅仅是简单的人工智能。如果大家对深度学习感兴趣,我相信各位一定会在搜索引擎上搜索过类似相关的关键字。我在Google上以deep learning作为关键字得到了2,630万个搜索的结果。这个数字比一周之前足足多出了300多万的结果。这个数字足以看得出来深度学习相关的内容发展的速度,人们对深度学习的关注也越来越高。

从另外的一个角度,我想让大家看看深度学习在市场上究竟有多么热门。从2011年到现在一共有140多家专注人工智能、深度学习相关的创业公司被收购。仅仅在2016年这种并购就发生了40多起。其中最疯狂的是就是Google,已经收购了 11 家人工智能创业公司,其中最有名的就是击败了李世石九段的 DeepMind。排名之后的就要数 Apple、Intel以及Twitter。以Intel 公司为例,仅在今年就已经收购了 3 家创业公司,Itseez、Nervana 和 Movidius。这一系列大手笔的并购为了布局人工智能以及深度学习的领域。

当我们去搜索深度学习话题的时候,经常会看到这样的一些晦涩难懂的术语:Gradient descent(梯度下降算法)、Backpropagation(反向传播算法)、Convolutional Neural Network(卷积神经网络)、受限玻耳兹曼机(Restricted Boltzmann Machine)等等。如你打开任何一篇技术文章,你看到的通篇都是各种数学公式。大家看到下面左边的图,其实并不是一篇高水准的学术论文,而仅仅是维基百科关于玻耳兹曼机的介绍。维基百科是科普层面的内容,内容复杂程度就超过了大多数数学知识的能力。

右边的那张图则是深度学习很流行的深度学习框架Theano 的一个简单的例子。对于大多数程序员而言学习这一类框架和程序代码的时候更让人抓狂,大段代码我们完全不明就里。我们看到的很多概念,对很多程序员来说觉得非常陌生,所以这确实是对程序员的一个很大的挑战。

在这样的背景之下,我今天的的话题可以归纳成三点:第一,我们为什么要学习深度学习;第二,深度学习最核心的关键概念就是神经网络,那么究竟什么是神经网络;第三,作为程序员,当我们想要成为深度学习开发者的时候,我们需要具备怎样的工具箱,以及从哪里着手进行开发。

为什么要学习深度学习

首先我们谈谈为什么要学习深度学习。在这个市场当中,最不缺乏的就是各种概念以及各种时髦新技术的词汇。深度学习有什么不一样的地方?我非常喜欢Andrew Ng(吴恩达)曾经用过的一个比喻。他把深度学习比喻成一个火箭。这个火箭有一个最重要的部分,就是它的引擎,目前来看在这个领域里面,引擎的核心就是神经网络。大家都知道,火箭除了引擎之外还需要有燃料,那么大数据其实就构成了整个火箭另外的重要组成部分——燃料。以往我们谈到大数据的时候,更多是强调存储和管理数据的能力,但是这些方法和工具更多是对于以往历史数据的统计、汇总。而对于今后未知的东西,这些传统的方法并不能够帮助我们可以从大数据中得出预测的结论。如果考虑到神经网络和大数据结合,我们才可能看清楚大数据真正的价值和意义。Andrew Ng就曾经说过“我们相信(神经网络代表的深度学习)是让我们获得最接近于人工智能的捷径”。这就是我们要学习深度学习的一个最重要的原因。

其次,随着我们进行数据处理以及运算能力的不断提升,深度学习所代表的人工智能技术和传统意义上人工智能技术比较起来,在性能上有了突飞猛进的发展。这主要得益于在过去几十间计算机和相关产业不断发展带来的成果。在人工智能的领域,性能是我们选择深度学习另一个重要的原因。

这是一段Nvidia 在今年公布的关于深度学习在无人驾驶领域应用的视频。我们可以看到,将深度学习应用在自动驾驶方面,仅仅经历了3千英里的训练,就可以达到什么样的程度。在今年年初进行的实验上,这个系统还不具备真正智能能力,经常会出现各种各样的让人提心吊胆的状况,甚至在某些情况下还需要人工干预。但经过了3千英里的训练之后,我们看到在山路、公路、泥地等各种复杂的路况下面,无人驾驶已经有了一个非常惊人的表现。请大家注意,这个深度学习的模型只经过了短短几个月、3千英里的训练。如果我们不断完善这种模型的话,这种处理能力将会变得何等的强大。这个场景里面最重要的技术无疑就是深度学习。我们可以得出一个结论:深度学习可以为我们提供强大的能力,如果程序员拥有了这个技术的话,无异于会让每个程序员如虎添翼。

神经网络快速入门

如果我们对于学习深度学习没有任何疑虑的话,接下来就一定会关心我需要掌握什么样的知识才能让我进入到这个领域。这里面最重要的关键技术就是“神经网络”。说起“神经网络”,容易混淆是这样两个完全不同的概念。一个是生物学神经网络,第二个才是我们今天要谈起的人工智能神经网络。可能在座的各位有朋友在从事人工智能方面的工作。当你向他请教神经网络的时候,他会抛出许多陌生的概念和术语让你听起来云里雾里,而你只能望而却步了。对于人工智能神经网络这个概念,大多数的程序员都会觉得距离自己有很大的距离。因为很难有人愿意花时间跟你分享神经网络的本质究竟是什么。而你从书本上读的到的理论和概念,也很让你找到一个清晰、简单的结论。

今天就我们来看一看,从程序员角度出发神经网络究竟是什么。我第一次知道神经网络这个概念是通过一部电影—1991年上映的《终结者2》。男主角施瓦辛格有一句台词:“My CPU is a neural-net processor; a learning computer.“(我的处理器是一个神经处理单元,它是一台可以学习的计算机)。从历史来看人类对自身智力的探索,远远早于对于神经网络的研究。1852年,意大利学者因为一个偶然的失误,将人类的头颅掉到硝酸盐溶液中,从而获得第一次通过肉眼关注神经网络的机会。这个意外加速了人对人类智力奥秘的探索,开启了人工智能、神经元这样概念的发展。

生物神经网络这个概念的发展,和今天我们谈的神经网络有什么关系吗?我们今天谈到的神经网络,除了在部分名词上借鉴了生物学神经网络之外,跟生物学神经网络已经没有任何关系,它已经完全是数学和计算机领域的概念,这也是人工智能发展成熟的标志。这点大家要区分开,不要把生物神经网络跟我们今天谈到的人工智能有任何的混淆。

神经网络的发展并不是一帆风顺的,这中间大概经历了三起三折的过程。

大约在1904年,人类已经对人脑的神经元有了最初步的认识和了解。1943年的时候,心理学家麦卡洛克 (McCulloch) 和数学家 Pitts 参考了生物神经元的结构,发表了抽象的神经元模型M。这个概念的提出,激发了大家对人智力探索的热情。到了1949年,有一个心理学家赫布(Hebb)提出了著名的Hebb模型,认为人脑神经细胞的突触上的强度上是可以变化的。于是计算科学家们开始考虑用调整权值的方法来让机器学习,这就奠定了今天神经网络基础算法的理论依据。到了1958年,计算科学家罗森布拉特(Rosenblatt)提出了由两层神经元组成的神经网络,并给它起了一个很特别的名字—“感知器”(Perceptron)。人们认为这就是人类智能的奥秘,许多学者和科研机构纷纷投入到对神经网络的研究中。美国军方也大力资助了神经网络的研究,并认为神经网络是比“曼哈顿工程”更重要的项目。这段时间直到1969年才结束,这个时期可以看作神经网络的一次高潮。事实上感知器只能做简单的线性分类任务。但是当时的人们热情太过于高涨,并没有清醒的认识到这点不足。于是,当人工智能领域的巨擘明斯基(Minsky)指出个问题的时候,事态就发生了反转。明斯基指出,如果将计算层增加到两层,则计算量过大并且缺少有效的学习算法。所以,他认为研究更深层的网络是没有价值的。明斯基在1969年出版了一本叫《Perceptron》的书,里面通过数学证明了感知器的弱点,尤其是感知器对XOR(异或)这样的简单分类任务都无法解决。由于明斯基在人工智能领域的巨大影响力以及书中呈现的明显的悲观态度,这很大多数多学者纷纷放弃了对于神经网络的研究。于是神经网络的研究顿时陷入了冰河期。这个时期又被称为“AI Winter”。将近十年以后,神经网络才会迎来复苏。

时间到了1986年,Rumelhar和Hinton提出了划时代的反向传播算法(Backpropagation,BP)。这个算法有效的解决了两层神经网络所需要的复杂计算量问题,从而带动了使用两层神经网络研究的热潮。我们看到的大部分神经网络的教材,都是在着重介绍两层(带一个隐藏层)神经网络的内容。这时候的Hinton 刚刚初露峥嵘,30年以后正是他重新定义了神经网络,带来了神经网络复苏的又一个春天。尽管早期对于神经网络的研究受到了生物学的很大的启发,但从BP算法开始研究者们更多是从数学上寻求问题的最优解,不再盲目模拟人脑网络。这是神经网络研究走向成熟的里程碑的标志。

90年代中期,由Vapnik等人提出了支持向量机算法(Support Vector Machines,支持向量机)。很快这个算法就在很多方面体现出了对比神经网络的巨大优势,例如:无需调参、高效率、全局最优解等。基于这些理由,SVM算法迅速打败了神经网络算法成为那个时期的主流。而神经网络的研究则再次陷入了冰河期。

在被人摒弃的十个年头里面,有几个学者仍然在坚持研究。这其中的很重要的一个人就是加拿大多伦多大学的Geoffery Hinton教授。2006年,他的在著名的《Science》杂志上发表了论文,首次提出了“深度信念网络”的概念。与传统的训练方式不同,“深度信念网络”有一个“预训练”(pre-training)的过程,这可以方便的让神经网络中的权值找到一个接近最优解的值,之后再使用“微调”(fine-tuning)技术来对整个网络进行优化训练。这两个技术的运用大幅度减少了训练多层神经网络的时间。在他的论文里面,他给多层神经网络相关的学习方法赋予了一个新名词— “深度学习”。

很快,深度学习在语音识别领域崭露头角。接着在2012年,深度学习技术又在图像识别领域大展拳脚。Hinton与他的学生在ImageNet竞赛中,用多层的卷积神经网络成功地对包含一千个类别的一百万张图片进行了训练,取得了分类错误率15%的好成绩,这个成绩比第二名高了将近11个百分点。这个结果充分证明了多层神经网络识别效果的优越性。从那时起,深度学习就开启了新的一段黄金时期。我们看到今天深度学习和神经网络的火热发展,就是从那个时候开始引爆的。

可以说在过去十几年时间里,图中这四位学者引领了深度学习发展最。第一位就是Yann LeCun,他曾在多伦多大学随 Hinton攻读博士后,现在是纽约大学的教授,同时还是Facebook人工智能最重要的推动者和科学家。第二位就是是之前我们多次提到的Geoffrey Hinton,现在是Google Brain。第三位是Bengio,他是蒙特利尔大学的教授,他仍然坚持在学术领域里面不断探索。Benjio主要贡献在于他对RNN(递归神经网络)的一系列推动。第四位是Andrew Ng(吴恩达),大家在很多媒体上见到过他。上个月他还来到北京参加过一次技术大会。因为他的华人身份更容易被大家接受。在纯理论研究上面Andrew Ng 的光芒不如上述三位大牛,甚至可以说有不小的差距,但是在工程方面的应用他仍然是人工智能领域的权威。

神经网络究竟可以用来干什么?神经网络如果放到简单概念上,可以理解成帮助我们实现一个分类器。对于绝大多数人工智能需求其实都可以简化成分类需求。更准确的描述就是绝大多数与智能有关的问题,都可以归结为一个在多维空间进行模式分类的问题

例如,识别一封邮件,可以告诉我们这是垃圾邮件或者是正常的邮件;或者进行疾病诊断,将检查和报告输入进去实现疾病的判断。所以说,分类器就是神经网络最重要的应用场景。

究竟什么是分类器,以及分类器能用什么方式实现这个功能?简单来说,将一个数据输入给分类器,分类器将结果输出。曾经有人问过这样一个问题,如果对一个非专业的人士,你如何用通俗表达方法向他介绍神经网络的分类器。有人就用了水果识别做为例子。例如,我非常喜欢吃苹果,当你看到一个新苹果,你想知道它是不是好吃是不是成熟,你鉴别的依据是很多年里你品尝过的许许多多的苹果。你会通过色泽、气味或其它的识别方法加以判断。这样判断过程在深度学习和神经网络里面,我们就称之为训练过的分类器。这个分类器建立完成之后,就可以帮助我们识别食入的每个苹果是不是成熟。对于传统的人工智能方法,例如逻辑回归来说,它的决策平面是线性的。所以,这一类的方法一般只能够解决样本是线性可分的情况。如果样本呈现非线性的时候,我们可以引入多项式回归。隐层的神经元对原始特征进行了组合,并提取出来了新的特征,而这个过程是模型在训练过程中自动“学习”出来的。

利用神经网络构建分类器,这个神经网络的结构是怎样的?

其实这个结构非常简单,我们看到这个图就是简单神经网络的示意图。神经网络本质上就是一种“有向图”。图上的每个节点借用了生物学的术语就有了一个新的名词 – “神经元”。连接神经元的具有指向性的连线(有向弧)则被看作是“神经”。这这个图上神经元并不是最重要的,最重要的是连接神经元的神经。每个神经部分有指向性,每一个神经元会指向下一层的节点。节点是分层的,每个节点指向上一层节点。同层节点没有连接,并且不能越过上一层节点。每个弧上有一个值,我们通常称之为”权重“。通过权重就可以有一个公式计算出它们所指的节点的值。这个权重值是多少?我们是通过训练得出结果。它们的初始赋值往往通过随机数开始,然后训练得到的最逼近真实值的结果作为模型,并可以被反复使用。这个结果就是我们说的训练过的分类器。

节点分成输入节点和输出节点,中间称为隐层。简单来说,我们有数据输入项,中间不同的多个层次的神经网络层次,就是我们说的隐层。之所以在这样称呼,因为对我们来讲这些层次是不可见的。输出结果也被称作输出节点,输出节点是有限的数量,输入节点也是有限数量,隐层是我们可以设计的模型部分,这就是最简单的神经网络概念。

如果简单做一个简单的类比,我想用四层神经网络做一个解释。左边是输入节点,我们看到有若干输入项,这可能代表不同苹果的RGB值、味道或者其它输入进来的数据项。中间隐层就是我们设计出来的神经网络,这个网络现在有不同的层次,层次之间权重是我们不断训练获得一个结果。最后输出的结果,保存在输出节点里面,每一次像一个流向一样,神经是有一个指向的,通过不同层进行不同的计算。在隐层当中,每一个节点输入的结果计算之后作为下一层的输入项,最终结果会保存在输出节点上,输出值最接近我们的分类,得到某一个值,就被分成某一类。这就是使用神经网络的简单概述。

除了从左到右的形式表达的结构图,还有一种常见的表达形式是从下到上来表示一个神经网络。这时候,输入层在图的最下方,输出层则在图的最上方。从左到右的表达形式以Andrew Ng和LeCun的文献使用较多。而在 Caffe框架里则使用的则是从下到上的表达。

简单来说,神经网络并不神秘,它就是有像图,利用图的处理能力帮助我们对特征的提取和学习的过程。2006年Hinton的那篇著名的论文中,将深度学习总结成三个最重要的要素:计算、数据、模型。有了这三点,就可以实现一个深度学习的系统。

程序员需要的工具箱

对于程序员来说,掌握理论知识是为了更好的编程实践。那就让我们我们来看看,对于程序员来说,着手深度学习的实践需要准备什么样的工具。

硬件

从硬件来讲,我们可能需要的计算能力,首先想到的就是CPU。除了通常的CPU架构以外,还出现了附加有乘法器的CPU,用以提升计算能力。此外在不同领域会有DSP的应用场景,比如手写体识别、语音识别、等使用的专用的信号处理器。还有一类就是GPU,这是一个目前深度学习应用比较热门的领域。最后一类就是FPGA(可编程逻辑门阵列)。这四种方法各有其优缺点,每种产品会有很大的差异。相比较而言CPU虽然运算能力弱一些,但是擅长管理和调度,比如读取数据,管理文件,人机交互等,工具也丰富。DSP相比而言管理能力较弱,但是强化了特定的运算能力。这两者都是靠高主频来解决运算量的问题,适合有大量递归操作以及不便拆分的算法。GPU 的管理能力更弱一些,但是运算能力更强。但由于计算单元数量多,更适合整块数据进行流处理的算法。FPGA在管理与运算处理方面都很强,但是开发周期长,复杂算法开发难度较大。就实时性来说,FPGA是最高的。单从目前的发展来看,对于普通程序员来说,现实中普遍采用的计算资源就还是是CPU以及GPU的模式,其中GPU是最热门的领域。

为什么是GPU?简单来说就是性能的表现导致这样的结果。随着CPU的不断发展,工艺水平逐步提高,我们开始担心摩尔定律会不会失效。但是GPU的概念横空出世,NVIDIA 的CEO 黄仁勋得意的宣称摩尔定律没有失效。我们看到最近几年,GPU处理能力的提升是非常惊人的。今年发布的Nvidia P100的处理能力已经达到令人恐怖的效果。与CPU处理能力做一个对比,虽然CPU的主频要远远高过GPU的主频,例如目前GPU在主频在0.5GHz到1.4gHz,处理单元达到3584个;而且最常见的CPU,比如Intel的处理器,大约只有20几个处理单元。这种差别是仅仅在处理单元的数量上就已经存在了巨大的差别。所以深度学习具备大量处理能力计算要求的情况下,GPU无疑具有非常强大的优势。

GPU并不是完全完美的方案!对于程序员来讲,我们也应该了解到它天生的不足。相比CPU,它仍然存在许多的局限。首先,比如:这种技术需要绑定特定的硬件、对编程语言的有一定的限制。简单来说,开发的灵活性不如CPU。我们习惯的CPU已经帮助我们屏蔽掉处理了许多的硬件上细节问题,而GPU则需要我们直接面对这些底层的处理资源进行编程。第二,在GPU领域不同厂商提供了不兼容的框架。应用的算法需要针对特定的硬件进行开发、完善。这也意味着采用了不同框架的应用对于计算环境的依赖。第三,目前GPU是通过PCIe外部配件的方式和计算机集成在一起。众所周知,PCIe连接的频宽是很大的瓶颈,PCIe 3.0 频宽不过7.877 Gbit/s。考虑到计算需求较大的时,我们会使用显卡构成GPU的集群(SLI),这个频宽的瓶颈对于性能而言就是一个很大的制约。最后,就是有限的内存容量的限制。现在Intel新推出的E7处理器的内存可以达到2TB。但是对于GPU而言,即使是Nvidia 的 P100 提供有16GB的内存,将四块显卡构成SLI(Scalable Link Interface)也只有64GB的显存容量。如果你的模型需要较大的内存,恐怕就需要做更好的优化才可以满足处理的需要。这些都是GPU目前的缺陷和不足。我们在着手使用GPU这种技术和资源的时候一定要意识到这一点。

GPU除了硬件上具备了一定的优势以外,Nvidia还为程序员提供了一个非常好的开发框架-CUDA。利用这个编程框架,我们通过简单的程序语句就可以访问GPUs中的指令集和并行计算的内存。对于这个框架下的并行计算内存,CUDA提供了统一管理内存的能力。这让我们可以忽略GPU的差异性。目前的编成接口是C语言的扩展,绝大多数主流编程语言都可以使用这个框架,例如C/C++、Java、Python以及.NET 等等。

今年的中秋节假期,我为自己DIY了一台深度学习工作站。起因是我买了一块GeForce GTX 1070显卡,准备做一些深度学习领域的尝试。因为我的老的电脑上PCIe 2.0 的插槽无法为新的显卡供电。不得已之下,只好更新了全部设备,于是就组装了一台我自己的深度学习工作站。这个过程是充满挑战的,这并不仅仅是需要熟悉各个部件的装配。最重要的是要考虑很多细节的的搭配的问题。比如说供电的问题,要计算出每个单元的能耗功率。这里面又一个重要的指标就是TDP( Thermal Design Power)。Intel 6850K的TDP值是140W,1070显卡的值是150W。于是,系统搭配的电源就选择了650W的主动电源。其次,如果我们用多块显卡(SLI),就必须考虑到系统频宽的问题。普通的CPU和主板在这方面有很大局限。就我的最基本的需求而言我需要的最大的PCI Expres Lanes 是 40。这样算下来,Intel i7-6850K就是我能找到最便宜而且可以达到要求的CPU了。

我在这两天的时间里面,走了很多弯路,所以就想跟大家分享一下我的经验。

第一,Linux在显卡驱动的兼容性方面有很多问题。大多数Linux 分发版本提供的 Nvidia显卡驱动是一个叫做Nouveau的开源版本的驱动。这个版本是通过逆向工程而开发的,对于新的Nvidia 的技术支持的很不好,所以一定要屏蔽这个驱动。第二,Nvida的驱动以及CUDA合cuDnn 的配置上也有很多搭配的问题。官方的版本只提供了针对特定Linux 分发版本的支持。相比较而言,Ubuntu 16.04 在这方面表现的更出色一些。再有就是CuDNN需要在Nvidia 官网注册以后才可以下载。第三,Nvidia 的驱动有很多版本。例如Nvidia P100架构的显卡需要最新的370版本才能支持,但是官网上可以下载的稳定版本只是367。最后,就是令人烦心的软件的依赖关系,安装的顺序等等。举一个例子,在GPU上编译Tensorflow 是不支持GCC 5.x的版本,只能自行安装 GCC 4.9并修改编译选项。另外,Bazel 也会对JDK 的版本有一定的要求。

除了自己去DIY一个深度学习工作站这个选项之外,另外一个选择就是采用云计算环境所提供的计算资源。不久之前 AWS 发布了最新一款深度学习的EC2实例类型,叫做p2。这个实例的类型使用了NVIDIA 的 K80的GPU,包括三种不同规格,第一种2xlarge,第二种是8xlarge,第三种是16xlarge。以p2.16xlarge为例,提供了16块K80 GPU ,GPU 显存达到了192G,并行处理单元的数量达到了惊人的39,936个。

当你在考虑去开发一个应用、去着手进行深度学习尝试的时候,我建议大家可以试试这种方式,这个选择可以很轻松的帮助我们计算资源以及硬件上各种麻烦的问题。

这是我前天为这次分享而准备的一个AWS 上p2的实例。仅仅通过几条命令就完成了实例的更新、驱动的安装和环境的设置,总共的资源创建、设置时间大概在10分钟以内。而之前,我安装调试前面提到的那台计算机,足足花了我两天时间。

另外,从成本上还可以做一个对比。p2.8xLarge 实例每小时的费用是7.2美元。而我自己那台计算机总共的花费了是¥16,904元。这个成本足够让我使用350多个小时的p2.8xLarge。在一年里使用AWS深度学习站就可以抵消掉我所有的付出。随着技术的不断的升级换代,我可以不断的升级我的实例,从而可以用有限的成本获得更大、更多的处理资源。这其实也是云计算的价值所在。

云计算和深度学习究竟有什么关系?今年的8月8号,在IDG网站上发表了一篇文章谈到了这个话题。文章中做了这样一个预言:如果深度学习的并行能力不断提高,云计算所提供的处理能力也不断发展,两者结合可能会产生新一代的深度学习,将带来更大影响和冲击。这个是需要大家考虑和重视的一个方向!

软件

深度学习除了硬件的基础环境之外。程序员会更关心与开发相关的软件资源。这里我罗列了一些自己曾经使用过的软件框架和工具。

  • Scikit-learn是最为流行的一个Python机器学习库。它具有如下吸引人的特点:简单、高效且异常丰富的数据挖掘/数据分析算法实现; 基于NumPy、SciPy以及matplotlib,从数据探索性分析,数据可视化到算法实现,整个过程一体化实现;开源,有非常丰富的学习文档。
  • Caffe专注在卷及神经网络以及图像处理。不过Caffe已经很久没有更新过了。这个框架的一个主要的开发者贾扬清也在今年跳槽去了Google。也许曾经的霸主地位要让位给他人了。
  • Theano 是一个非常灵活的Python 机器学习的库。在研究领域非常流行,使用上非常方便易于定义复杂的模型。Tensorflow 的API 非常类似于Theano。我在今年北京的QCon 大会上也分享过关于Theano 的话题。
  • Jupyter notebook 是一个很强大的基于ipython的python代码编辑器,部署在网页上,可以非常方便的进行交互式的处理,很适合进行算法研究合数据处理。
  • Torch 是一个非常出色的机器学习的库。它是由一个比较小众的lua语言实现的。但是因为LuaJIT 的使用,程序的效率非常出色。Facebook在人工智能领域主打Torch,甚至现在推出了自己的升级版框架Torchnet。

深度学习的框架非常之多,是不是有一种乱花渐欲迷人眼的感觉?我今天向各位程序员重点介绍的是将是TensorFlow。这是2015年谷歌推出的开源的面向机器学习的开发框架,这也是Google第二代的深度学习的框架。很多公司都使用了TensorFlow开发了很多有意思的应用,效果很好。

用TensorFlow可以做什么?答案是它可以应用于回归模型、神经网络以深度学习这几个领域。在深度学习方面它集成了分布式表示、卷积神经网络(CNN)、递归神经网络(RNN) 以及长短期记忆人工神经网络(Long-Short Term Memory, LSTM)。关于Tensorflow 首先要理解的概念就是Tensor。在辞典中对于这个词的定义是张量,是一个可用来表示在一些向量、标量和其他张量之间的线性关系的多线性函数。实际上这个表述很难理解,用我自己的语言解释Tensor 就是“N维数组”而已。

使用 TensorFlow, 作为程序员必须明白 TensorFlow这样几个基础概念:它使用图 (Graph) 来表示计算任务;在被称之为 会话 (Session) 的上下文 (context) 中执行图;使用 Tensor 表示数据;通过 变量 (Variable) 维护状态;使用 feed 和 fetch 可以为任意的操作(arbitrary operation) 赋值或者从其中获取数据。

一句话总结就是,TensorFlow 就是有状态图的数据流图计算环境,每个节点就是在做数据操作,然后提供依赖性和指向性,提供完整数据流。

TensorFlow安装非常简单,但官网提供下载的安装包所支持的CUDA 的版本是7.5。考虑到CUDA 8 的让人心动的新特以及不久就要正式发布的现状。或许你想会考虑立即体验CUDA 8,那么就只能通过编译Tensorflow源代码而获得。目前TensorFlow已经支持了Python2.7、3.3+。此外,对于使用Python 语言的程序员还需要安装所需要的一些库,例如:numpy、protobuf等等。对于卷积处理而言,cuDNN是公认的性能最好的开发库,请一定要安装上。常规的Tensorsorflow的安装很简单,一条命令足矣:

$ pip3 install —upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.11.0rc0-cp35-cp35m-linux_x86_64.whl

如果想评估一下或者简单学习一下,还可以通过Docker进行安装,安装的命令如下:

$ docker run -it -p 8888:8888 gcr.io/tensorflow/tensorflow

TensorFlow有很多优点。首先,目前为止,深度学习的开发框架里面TensorFlow的文档做的最好,对程序员学习而言是非常好的一点。第二,TensorFlow有丰富的参考实例,作为参考学习起来非常容易。第三,开发者社区活跃,在任何一个深度学习的社区里,都有大量关于TensorFlow的讨论。第四,谷歌的支持力度非常大,从2015年到现在升级速度非常快,这是其他开源框架远远达不到的结果。

参考TensorFlow的白皮书,我们会看到未来TensorFlow还将会有巨大的发展潜力。让我特别感兴趣是这两个方向。第一,支持跨多台机器的 parallelisation。尽管在0.8版本中推出了并行化的能力,但是目前还不完善。随着未来不断发展,依托云计算的处理能力的提升这个特性将是非常让人振奋的。第二,支持更多的开发语言,对于开发者来说这是一个绝大的利好,通过使用自己擅长的语言使用TensorFlow应用。这些开发语言将会扩展到Java、Lua以及R 等。

在这里我想给大家展示一个应用Tensorflow 的例子。这个例子的代码托管在这个网址上 https://github.com/anishathalye/neural-style。白俄罗斯的现代印象派艺术家Leonid Afremov善于用浓墨重彩来表现都市和风景题材,尤其是其雨景系列作品。他习惯用大色块的铺陈来营造光影效果,对反光物体和环境色的把握非常精准。于是我就找到了一张上海东方明珠电视塔的一张摄影作品,我希望通过Tensorflow 去学习一下Leonid Afremov 的绘画风格,并将这张东方明珠的照片处理成那种光影色彩丰富的作品风格。利用Tensorflow 以及上面提到的那个项目的代码,在一个AWS 的p2类型的实例上进行了一个一千次的迭代,于是就得到了下图这样的处理结果。

这个处理的代码只有350行里,模型使用了一个成名于2014年ImageNet比赛中的明星 VGG。这个模型非常好,特点就是“go depper”。

TensorFlow 做出这样的作品,并不仅仅作为娱乐供大家一笑,还可以做更多有意思的事情。将刚才的处理能力推广到视频当中,就可以看到下图这样的效果,用梵高著名的作品”星月夜“的风格就加工成了这样新的视频风格。

可以想象一下,如果这种处理能力在更多领域得以应用,它会产生什么样的神奇的结果?前景是美好的,让我们有无限遐想。事实上我们目前所从事的很多领域的应用开发都可以通过使用神经网络和深度学习来加以改变。对于深度学习而言,掌握它并不是难事。每一个程序员都可以很容易的掌握这种技术,利用所具备的资源,让我们很快成为深度学习的程序开发人员。

结束语

未来究竟是什么样,我们没有办法预言。有位作家Ray Kurzweil在2005年写了《奇点临近》一书。在这本书里面他明确告诉我们,那个时代很快到来。作为那个时代曙光前的人群,我们是不是有能力加速这个过程,利用我们学习的能力实现这个梦想呢?

作者介绍:

费良宏

亚马逊AWS首席云计算技术顾问,拥有超过20年在IT行业以及软件开发领域的工作经验。在此之前他曾经任职于Microsoft、Apple等知名企业,任职架构师、技术顾问等职务,参与过多个大型软件项目的设计、开发与项目管理。目前专注于云计算以及互联网等技术领域,致力于帮助中国的开发者构建基于云计算的新一代的互联网应用。