Keras深度学习实战

978-7-115-48222-8
作者: [意大利]安东尼奥·古利(Antonio Gulli) [印度]苏伊特·帕尔(Sujit Pal)
译者: 王海玲李昉
编辑: 王峰松

图书目录:

详情

作为一款轻量级、模块化的开源深度学习框架,Keras以容易上手、利于快速原型实现、能够与TensorFlow和Theano等后端计算平台很好兼容等优点,深受众多开发人员和研究人员的喜爱。

本书结合大量实例,简明扼要地介绍了目前热门的神经网络技术和深度学习技术。从经典的多层感知机到用于图像处理的深度卷积网络,从处理序列化数据的循环网络到伪造仿真数据的生成对抗网络,从词嵌入到AI游戏应用中的强化学习,本书引领读者一层一层揭开深度学习的面纱,并在逐渐清晰的理论框架下,提供多个Python编码实例,方便读者动手实践。

通过阅读本书,读者不仅能学会使用Keras快捷构建各个类型的深度网络,还可以按需自定义网络层和后端功能,从而提升自己的AI编程能力,在成为深度学习专家的路上更进一步。


本书特色

本书为软件工程师和数据科学家而编写,书中简明而全面地介绍了目前的神经网络和深度学习技术。全书展示了基于Keras框架、以Python编码的20多种有效的神经网络。

你将从本书中学到以下内容:

在大型神经网络上使用反向传播算法逐步优化函数

微调神经网络以改进结果质量

使用深度学习进行图像和音频处理

在特定的案例中使用递归神经张量网络(RNTN)以取得比标准词嵌入更好的效果

识别循环神经网络(RNN)适于解决的问题

探索自动编码机的实现过程

使用强化学习增强深层神经网络

图书摘要

版权信息

书名:Keras深度学习实战

ISBN:978-7-115-48222-8

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    [意大利] 安东尼奥•古利(Antonio Gulli)

     [印度] 苏伊特•帕尔(Sujit Pal)

译    王海玲 李 昉

责任编辑 王峰松

审  校 于立国

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Copyright © 2017 Packt Publishing. First published in the English language under the title Deep Learning with Keras, ISBN 978-1-78712-842-2.

All rights reserved.

本书中文简体字版由Packt Publishing公司授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。

版权所有,侵权必究。


作为一款轻量级、模块化的开源深度学习框架,Keras以容易上手、利于快速原型实现、能够与TensorFlow和Theano等后端计算平台很好兼容等优点,深受众多开发人员和研究人员的喜爱。

本书结合大量实例,简明扼要地介绍了目前热门的神经网络技术和深度学习技术。从经典的多层感知机到用于图像处理的深度卷积网络,从处理序列化数据的循环网络到伪造仿真数据的生成对抗网络,从词嵌入到AI游戏应用中的强化学习,引领读者一层一层揭开深度学习的面纱,并在逐渐清晰的理论框架下,提供多个Python编码实例,方便读者动手实践。

通过阅读本书,读者不仅能学会使用Keras快捷构建各个类型的深度网络,还可以按需自定义网络层和后端功能,从而提升自己的AI编程能力,在成为深度学习专家的路上更进一步。


绕开晦涩的理论和艰深的数学逻辑,你可以像搭建乐高积木一样搭建自己的深度学习模型,是不是很神奇呢?这就是Keras框架带给我们的乐趣。而本书作为一本展现诸多实现细节的指导书,定会成为你桌头案边的最佳伙伴。

——云从科技副总裁 张立

Keras是深度学习领域最受欢迎的框架之一。译者李昉一直在集智俱乐部参与学术文章的翻译工作。本书的出版对有志于了解、学习深度学习的读者来说是一个非常好的消息。

——北京师范大学系统科学学院教授,博士生导师,集智俱乐部、AI学园创始人,腾讯研究院、阿里研究院、网络智库专家 张江

很高兴看到这本书中文译本的出版。本书译者都曾在我的培训班学习,他们为此付出很多时间。如果你了解一些深度学习理论,如果你想快速构建自己的应用,那么这本书无疑可以给你提供巨大的帮助。

——炼数成金创始人、首席科学家 黄志洪

Keras为支持快速实验而生,这个基于模块化和易扩展性的API一直以“user friendly”著称。作者Antonio Gulli作为谷歌在机器学习领域重量级专家之一,发表过很多篇有行业影响力的专业论述。本书是一本实用操作手册,译者也是深耕机器学习领域的先行者和实践者,强烈推荐给所有致力于在此领域摸索和创新的从业者。

——上海前隆信息科技有限公司数据中心总监 苏波

本书以由浅入深、由原理到场景的方式介绍了深度学习框架Keras的应用。通过基础神经网络到复杂模型的深度剖析,配以丰富的实例展示,让每一位读者都能深刻地体会到Keras及深度学习的魅力。本书的中文译本忠实于英文原著,讲解详尽,内容充实,是每一位深度学习的技术爱好者必读的书目,也是每一位Keras爱好者的必备宝典。

——Splunk系统架构师 张天犁


作者Antonio Gulli是企业领导和软件部门高管,极具创新精神和执行力,并乐于发现和管理全球高科技人才。他是搜索引擎、在线服务、机器学习、信息检索、数据分析以及云计算等多方面的专家。目前,他幸运地拥有欧洲4个不同国家的工作经验,并管理过来自欧洲和美国6个不同国家的员工。Antonio在出版业(Elsevier)、消费者互联网(Ask.com 和Tiscali)以及高科技研发(微软和谷歌)等多个跨度的行业里历任CEO、GM、CTO、副总裁、总监及区域主管。

我要感谢我的共同作者Sujit Pal,他如此聪明、谦逊,并总是乐于提供帮助。我一直很赞赏他的团队精神,这种精神成就了本书。

我要感谢Francois Chollet(以及Keras的其他的很多贡献者),他们花费了大量时间和精力构建了这个如此容易上手但又不牺牲过多功能的深度学习工具。

我还要感谢本书的编辑们,来自Packt的Divya Poojari、Cheryl Dsa和Dinesh Pawar,以及来自Packt和谷歌的审稿者,非常感谢他们的支持和诸多有价值的建议。如果没有他们就没有本书。

我要感谢我在谷歌工作时的经理Brad以及同事Mick和Corrado,他们鼓励我撰写本书,并一直帮助我审核书中内容。

我要感谢位于华沙的知名茶馆和咖啡厅Same Fusy,我就是在这里喝茶时获得了编写本书的灵感,这里的茶是从上百种选择里选出来的。这个地方很棒,如果你正在寻找一个激发你创造力的地方,我强烈推荐你来这里。

我还要感谢谷歌的HRBP对我将本书版税悉数捐献给民族多样性奖学金的支持。

我要感谢我的朋友Eric、Laura、Francesco、Ettore和Antonella在我需要的时候给予我的帮助。友谊之树常青,你们是我永远的朋友。

我要感谢我的儿子Lorenzo对我加入谷歌的鼓励,感谢我儿子Leonardo持久发现新事物的热忱,感谢我女儿Aurora每天都带给我微笑。

最后感谢我的父亲Elio、母亲Maria给我的爱。

Sujit Pal是Elsevier Labs技术研发主管,致力于构建围绕研发内容和元数据的智能系统。他的主要兴趣包括信息检索、本体论、自然语言处理、机器学习,以及分布式处理。他现在的工作是利用深度学习模型对图像进行分类和相似度识别。在此之前,他在客户卫生保健行业工作,帮助构建基于本体论的语义搜索、关联广告,以及EMR数据处理平台。他在他的博客Salmon Run上发表技术文章。

我要感谢本书的共同作者Antonio Gulli,感谢他邀请我共同写作本书。这对我是一个非常难得的机会,我从中学到了很多。假如他不曾邀请我,我就绝不可能取得今日的成绩。

我要感谢Elsevier实验室的主管Ron Daniel和首席架构师Bradley P Allen,他们引导我进入深度学习的领域,并让我对此痴迷不已。

我要感谢Francois Chollet(以及Keras的其他的很多贡献者),他们花费了大量时间和精力构建了这个如此容易上手但又不牺牲过多功能的深度学习工具。

感谢来自Packt的编辑们——Divya Poojari、Cheryl Dsa和Dinesh Pawar,以及来自Packt和谷歌的审稿者,非常感谢他们的支持和诸多有价值的建议。如果没有他们就没有本书。

我要感谢我历年的同事和经理们,特别是那些曾经帮助过我并让我的职业生涯不断进取、改变的人们。

最后,我要感谢我的家人,在过去的几个月里容忍我工作第一、写书第二,然后才是顾家。希望你们都觉得这是值得的。


Nick McClure是一名资深数据科学家,现供职于美国西雅图市的PayScale公司。此前,他曾在Zillow和凯撒娱乐工作。他分别于蒙大拿大学、圣本迪克学院和圣约翰大学获得应用数学的相关学位。Nick著有一本由Packt出版公司出版的书籍《TensorFlow Machine Learning Cookbook》。他热衷于学习研究数据分析、机器学习和人工智能技术。有时他会把突然得到的奇思妙想发表在他的博客上或是他的推特上。


王海玲

大学毕业于吉林大学计算机系,从小喜爱数学,曾获得华罗庚数学竞赛全国二等奖。拥有世界500强企业多年研发经验。作为项目骨干成员,参与过美国惠普实验室机器学习项目。

李 昉

毕业于东北大学自动化系,大学期间曾获得“挑战杯”全国一等奖。拥有世界500强企业多年研发经验,随后加入互联网创业公司。2013年开始带领研发团队将大数据分析运用于“预订电商”价格分析预测(《IT经理世界》2013年第6期)。现在中体彩彩票运营公司负责大数据和机器学习方面的研发。同时是集智俱乐部成员,参与翻译人工智能图书《Deep Thinking》。


于立国,现任国美大数据研究院研发总监,曾任知名上市互联网广告公司——品众互动研发总监,也曾在Adobe数字化营销部门担任资深负责人,对大数据、人工智能、互联网广告领域深有研究。


本书特为软件工程师和数据科学家编写,书中简明而全面地介绍了目前的神经网络、人工智能和深度学习技术。

这本书展示了基于Keras框架、以Python编码的20多种有效的神经网络。Keras是一个模块化的神经网络库,它能运行于谷歌的TensorFlow和Lisa实验室的Theano的后端之上。

本书循序渐进地介绍了简单线性回归、传统多层感知机,以及更复杂的深度卷积网络和生成对抗网络等监督学习算法。另外,本书还介绍了自动感知机和生成式网络等非监督学习算法,并详细阐述了回归网络和长短期记忆网络(LSTM)。本书后续章节将陆续介绍Keras的各种函数API,以及用户实例在现有的丰富的函数库没有涵盖的情况下,如何自定义Keras。本书还探讨了用前面提到的模块构造更大型、更复杂的系统。本书最后介绍了深度强化学习和如何应用其构建游戏AI。

练习的应用程序代码包括新闻分类、文本句法分析、情感分析、人工文本合成,以及语音标注。我们也探讨了图像处理技术,包括如何识别手写数字图像、图像的自动归类,以及基于相关图像注释的高级对象识别。我们还提供了一个面部凸点检测识别的实例。声音识别包括了对来自不同讲话者的离散语音识别。强化学习则被用来构建一个可以自主玩游戏的深度Q学习网络。

实验是本书的核心,通过多个变量改变输入的参数、网络模型、损失函数和优化算法,我们得以逐步改进神经网络的学习性能。我们还会比较不同CPU和GPU运行条件下的训练效率。

人工智能是一个非常广泛的研究领域,主要研究如何让机器表现出人类的认知能力,例如学习行为、和环境的主动交互、演绎推理、计算机视觉、语音识别、问题解决、知识展现、感知能力等(更多信息请参考《Artificial Intelligence: A Modern Approach》,作者S. Russell和P. Norvig,Prentice Hall,2003)。通俗来讲,人工智能就是任何让机器模仿人类的智能行为的技术。人工智能从计算机科学、数学和统计学等学科中获得了很大的启发。

机器学习是人工智能的一个分支,主要研究如何使机器在不必额外编程的情况下,学会执行特定任务(更多信息请参考《Pattern Recognition and Machine Learning》,作者C. M. Bishop,Springer,2006)。事实上,机器学习的核心思想在于可以通过创建算法让机器通过数据进行学习并预测数据。现在的机器学习有3个大的分类:第一种是监督学习,机器通过已知的输入和对应的预期输出进行样本训练,以对全新的未知数据进行有意义的预测;第二种是无监督学习,机器只能通过输入的数据,在没有外界监督的情况下自己发现有意义的结构;第三种是强化学习,机器作为同环境进行交互的代理,学习哪些行为能获得奖赏。

深度学习是利用人工神经网络进行机器学习的方法论里的一个特定子集,如图0.1所示。而人工神经网络的灵感来自于人类大脑神经元的结构(更多信息请参考文章《Learning Deep Architectures for AI》,作者Y. Bengio,Found. Trends,vol. 2,2009)。非正式地讲,deep这个词通常指的是人工神经网络中存在多个层次,但这种说法已随着时间的推移而改变。4年前,10层就是一个很高效的深度学习网络,而今天,至少几百层的网络才被认为是深度的。

图0.1

深度学习对机器学习来说是一次真正的海啸(更多信息请参考《Computational Linguistics and Deep Learning》,作者C.D.Manning,Computational Linguistics,vol. 41,2015),它虽然只有相对较少的巧妙的方法,却被成功地应用到非常多的不同的领域(图像、文本、视频、语音和视觉),显著改进了过去几十年的技术发展水平。深度学习的成功还因为现在有了更多的可用于训练的数据(如来自ImageNet的图像),以及可用于高效数值计算的相对低廉、可用的GPU。谷歌、微软、亚马逊、苹果、脸书,以及其他很多公司每天都在应用这种深度学习技术进行大量的数据分析。目前,此类专项工作不再局限于纯学术研究领域以及大型工业化公司,它已经成为软件产业里一个不可分割的部分,读者应该对此有所掌握。本书不要求特定的数学背景知识,但我们将假设读者是一个Python程序员。

第1章,神经网络基础,讲述神经网络的基础知识。

第2章,Keras安装和API,展示如何在AWS、Microsoft Azure、Google Cloud,以及你自己的机器上安装Keras,并提供对Keras API的概览。

第3章,深度学习之卷积网络,介绍卷积网络的概念。这是深度学习的一个重要创新,最初的构想是为了图像处理,但现在在文本、视频和语音等多领域都有成功的应用。

第4章,生成对抗网络和WaveNet,介绍了利用生成对抗网络来合成如同人类自己产生的数据。我们还会介绍WaveNet,这是一个可用于生成高质量人类语音以及乐器音的深度神经网络。

第5章,词嵌入,讨论词向量相关的一套深度学习方法,用于检测词汇和相似语义词汇组的关系。

第6章,循环神经网络RNN,讲述循环神经网络的技术和应用,这是一类优化过的用于处理文本等序列化数据的网络。

第7章,其他深度学习模型,简要介绍Keras API、回归网络,以及自动编码机等。

第8章,游戏中的AI,教你如何进行深度强化学习,以及如何用Keras构建基于奖赏反馈的街机游戏玩儿法的深度学习网络。

第9章,结束语,快速回顾本书内容,并向用户介绍Keras 2.0的新特性。

为了让您流畅地阅读各个章节,你需要准备以下软件:

TensorFlow 1.0.0或者更高版本;

Keras 2.0.2或者更高版本;

Matplotlib 1.5.3或者更高版本;

Scikit-learn 0.18.1或者更高版本;

NumPy 1.12.1或者更高版本。

推荐硬件清单如下:

32位或者64位架构;

2GHz以上CPU;

4GB RAM;

至少10GB硬盘空间。

如果您是有经验的机器学习数据科学家或者有过神经网络实践的人工智能程序员,您会发现这是一本很好的关于Keras深度学习的入门教材。

阅读本书需要一些Python的知识。


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供如下资源:

要获得以上配套资源,请在异步社区本书页面中点击 ,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


人工神经网络表示一类机器学习的模型,最初是受到了哺乳动物中央神经系统研究的启发。网络由相互连接的分层组织的神经元组成,这些神经元在达到一定条件时就会互相交换信息(专业术语是激发(fire))。最初的研究开始于20世纪50年代后期,当时引入了感知机(Perceptron)模型(更多信息请参考文章《The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain》,作者F. Rosenblatt,Psychological Review,vol. 65,pp. 386~408,1958)。感知机是一个可以实现简单操作的两层网络,并在20世纪60年代后期引入反向传播算法(backpropagation algorithm)后得到进一步扩展,用于高效的多层网络的训练(据以下文章《Backpropagation through Time: What It Does and How to Do It》,作者P. J. Werbos,Proceedings of the IEEE, vol. 78,pp. 1550~1560,1990;《A Fast Learning Algorithm for Deep Belief Nets》,作者G. E. Hinton,S. Osindero,Y. W. Teh,Neural Computing,vol. 18,pp. 1527~1554,2006)。有些研究认为这些技术起源可以追溯到比通常引述的更早的时候(更多信息,请参考文章《Deep Learning in Neural Networks: An Overview》,作者J. Schmidhuber,Neural Networks,vol. 61,pp. 85~117,2015)。直到20世纪80年代,人们才对神经网络进行了大量的学术研究,那时其他更简单的方法正变得更加有用。然后,由于G.Hinton提出的快速学习算法(更多信息,请参考文章《The Roots of Backpropagation: From Ordered Derivatives to Neural Networks and Political Forecasting》,作者S. Leven,Neural Networks,vol. 9,1996;《Learning Representations by Backpropagating Errors》,作者D. E. Rumelhart,G. E. Hinton,R. J. Williams,Nature,vol. 323,1986),以及2011年前后引入GPU后使大量数值计算成为可能,开始再度出现了神经网络研究的热潮。

这些进展打开了现代深度学习的大门。深度学习是以一定数量网络层的神经元为标志的神经网络,它可以基于渐进的层级抽象学习相当复杂的模型。几年前,3~5层的网络就是深度的,而现在的深度网络已经是指100~200层。

这种渐进式抽象的学习模型,模仿了历经几百万年演化的人类大脑的视觉模型。人类大脑视觉系统由不同的层组成。我们人眼关联的大脑区域叫作初级视觉皮层V1,它位于大脑后下方。视觉皮层为多数哺乳动物所共有,它承担着感知和区分视觉定位、空间频率以及色彩等方面的基本属性和微小变化的角色。据估计,初级视觉层包含了1亿4000万个神经元,以及100亿个神经元之间的连接。V1层随后和其他视觉皮层V2、V3、V4、V5和V6连接,以进一步处理更复杂的图像信息,并识别更复杂的视觉元素,如形状、面部、动物等。这种分层组织是1亿年间无数次尝试的结果。据估计,人类大脑包含大约160亿个脑皮质神经细胞,其中10%~25%是负责视觉信息处理的(更多信息,请参考文章《The Human Brain in Numbers: A Linearly Scaled-up Primate Brain》,作者 S. Herculano-Houzel,vol. 3,2009)。深度学习就是从人类大脑视觉系统的层次结构中获得了启发,前面的人工神经网络层负责学习图像基本信息,更深的网络层负责学习更复杂的概念。

本书涵盖了神经网络的几个主要方面,并提供了基于Keras和最小有效Python库作为深度学习计算的可运行网络实例编码,后端基于谷歌的TensorFlow或者蒙特利尔大学的Theano框架。

好的,让我们切入正题。

在本章,我们将介绍以下内容:

感知机是一个简单的算法,给定n维向量xx1, x2, …, xn)作为输入,通常称作输入特征或者简单特征,输出为1(是)或0(否)。数学上,我们定义以下函数:

这里,w是权重向量,wx是点积(译者注:也称内积、数量积或标量积)b是偏差。如果你还记得基础的几何知识,就应该知道wx+b定义了一个边界超平面,我们可以通过设置wb的值来改变它的位置。如果x位于直线之上,则结果为正,否则为负。非常简单的算法!感知机不能表示非确定性答案。如果我们知道如何定义wb,就能回答是(1)或否(0)。接下来我们将讨论这个训练过程。

Keras的原始构造模块是模型,最简单的模型称为序贯模型,Keras的序贯模型是神经网络层的线性管道(堆栈)。以下代码段定义了一个包含12个人工神经元的单层网络,它预计有8个输入变量(也称为特征):

from keras.models import Sequential
model = Sequential()
model.add(Dense(12, input_dim=8, kernel_initializer='random_uniform'))

每个神经元可以用特定的权重进行初始化。Keras提供了几个选择,其中最常用的选择如下所示。

完整选项列表请参考Keras官网。

在本章中,我们将定义一个多层线性网络,并将其作为本书的第一个代码示例。从历史上来看,感知机这个名称是指具有单一线性层的模型,因此,如果它有多层,我们就可以称之为多层感知机(Multilayer perceptron,MLP)。图1.1展示了一个一般的神经网络,它具有一个输入层、一个中间层和一个输出层。

图1.1

在图1.1中,第一层中的每个节点接收一个输入,并根据预设的本地决策边界值确定是否激发。然后,第一层的输出传递给中间层,中间层再传递给由单一神经元组成的最终的输出层。有趣的是,这种分层组织似乎模仿了我们前面讨论过的人类的视觉系统。

全连接的网络是指每层中的每个神经元和上一层的所有神经元有连接,和下一层的所有神经元也都有连接。

让我们来考虑一个单一的神经元如何选择最佳的权重w和偏差b?理想情况下,我们想提供一组训练样本,让机器通过调整权重值和偏差值,使输出误差最小化。为了更加的具体,我们假设有一组包含猫的图像,以及另外单独的一组不包含猫的图像。为了简单起见,假设每个神经元只考虑单个输入像素值。当计算机处理这些图像时,我们希望我们的神经元调整其权重和偏差,使得越来越少的图像被错误识别为非猫。这种方法似乎非常直观,但是它要求权重(和/或偏差)的微小变化只会在输出上产生微小变化。

如果我们有一个较大的输出增量,我们就不能进行渐进式学习(而非在所有的方向上进行尝试——这样的过程称为穷举搜索——我们不知道是否在改进)。毕竟,小孩子是一点一点学习的。不幸的是,感知机并不表现出这种一点一点学习的行为,感知机的结果是0或1,这是一个大的增量,它对学习没有帮助,如图1.2所示。

我们需要一些更平滑的东西,一个从0到1逐渐变化不间断的函数。在数学上,这意味着我们需要一个可以计算其导数的连续的函数。

图1.2

sigmoid函数的定义如下:

如图1.3所示,当输入在(−∞,∞)的区间上变化时,位于(0,1)区间上的输出值变化很小。从数学的角度讲,该函数是连续的。典型的sigmoid函数如图1.3所示。

图1.3

神经元可以使用sigmoid来计算非线性函数σ(z=wx+b)。注意,如果z=wx+b是非常大的正值,那么ez→0,因而σ(z)→1;而如果z=wx+b是非常大的负值,ez→∞,因而σ(z)→0。换句话说,以sigmoid为激活函数的神经元具有和感知机类似的行为,但它的变化是渐进的,输出值如0.553 9或0.123 191非常合理。在这个意义上,sigmoid神经元可能正是我们所要的。

sigmoid并非可用于神经网络的唯一的平滑激活函数。最近,一个被称为修正线性单元(Rectified Linear Unit,ReLU)的激活函数很受欢迎,因为它可以产生非常好的实验结果。

ReLU函数简单定义为f(x)=max(0,x),这个非线性函数如图1.4所示。对于负值,函数值为零;对于正值,函数呈线性增长。

图1.4

在神经网络领域,sigmoid和ReLU通常被称为激活函数。在“Keras中的不同优化器测试”一节中,我们将看到,那些通常由sigmoid和ReLU函数产生的渐进的变化,构成了开发学习算法的基本构件,这些构件通过逐渐减少网络中发生的错误,来一点一点进行调整。图1.5给出了一个使用σ激活函数的例子,其中(x1, x2, …, xm)为输入向量,(w1, w2, …, wm)为权重向量,b为偏差,表示总和。

图1.5

Keras支持多种激活函数,完整列表请参考Keras官网。

在本节中,我们将构建一个可识别手写数字的网络。为此,我们使用MNIST数据集,这是一个由60 000个训练样例和10 000个测试样例组成的手写数字数据库。训练样例由人标注出正确答案,例如,如果手写数字是“3”,那么“3”就是该样例关联的标签。

在机器学习中,如果使用的是带有正确答案的数据集,我们就说我们在进行监督学习。 在这种情况下,我们可以使用训练样例调整网络。测试样例也带有与每个数字关联的正确答案。然而,这种情况下,我们要假装标签未知,从而让网络进行预测,稍后再借助标签来评估我们的神经网络对于识别数字的学习程度。因此,如你所料,测试样例只用于测试我们的网络。

每个MNIST图像都是灰度的,它由28×28像素组成。这些数字的一个子集如图1.6所示。

图1.6

在很多应用中,将类别(非数字)特征转换为数值变量都很方便。例如,[0-9]中值为d的分类特征数字可以编码为10位二进制向量,除了第d位为1,其他位始终为0。 这类表示法称为 One-hot编码(OHE),当数据挖掘中的学习算法专门用于处理数值函数时,这种编码的使用非常普遍。

这里,我们使用Keras定义一个识别MNIST手写数字的网络。我们从一个非常简单的神经网络开始,然后逐步改进。

Keras提供了必要的库来加载数据集,并将其划分成用于微调网络的训练集X_train,以及用于评估性能的测试集X_test。数据转换为支持GPU计算的float32类型,并归一化为[0, 1]。另外,我们将真正的标签各自加载到Y_train和Y_test中,并对其进行One-hot编码。我们来看以下代码:

from __future__ import print_function
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import SGD
from keras.utils import np_utils
np.random.seed(1671) #重复性设置

#网络和训练
NB_EPOCH = 200
BATCH_SIZE = 128
VERBOSE = 1
NB_CLASSES = 10 #输出个数等于数字个数
OPTIMIZER = SGD()#SGD优化器,本章稍后介绍
N_HIDDEN = 128
VALIDATION_SPLIT=0.2 #训练集中用作验证集的数据比例

#数据:混合并划分训练集和测试集数据
#
(X_train, y_train), (X_test, y_test) = mnist.load_data()
#X_train是60 000行28×28的数据,变形为60000×784
RESHAPED = 784
#
X_train = X_train.reshape(60000, RESHAPED)
X_test = X_test.reshape(10000, RESHAPED)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
# 归一化
#
X_train /= 255
X_test /= 255
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
#将类向量转换为二值类别矩阵
Y_train = np_utils.to_categorical(y_train, NB_CLASSES)
Y_test = np_utils.to_categorical(y_test, NB_CLASSES)

输入层中,每个像素都有一个神经元与其关联,因而共有28×28 = 784个神经元,每个神经元对应MNIST图像中的一个像素。

通常来说,与每个像素关联的值被归一化到[0,1]区间中(即每个像素的亮度除以255,255是最大亮度值)。 输出为10个类别,每个数字对应一个类。

最后一层是使用激活函数softmax的单个神经元,它是sigmoid函数的扩展。softmax将任意k维实向量压缩到区间(0, 1)上的k维实向量。在我们的例子中,它聚合了上一层中由10个神经元给出的10个答案。

#10个输出
#最后是softmax激活函数
model = Sequential()
model.add(Dense(NB_CLASSES, input_shape=(RESHAPED,)))
model.add(Activation('softmax'))
model.summary()

一旦我们定义好模型,我们就要对它进行编译,这样它才能由Keras后端(Theano或TensorFlow)执行。编译期间有以下几个选项。

目标函数的一些常见选项(Keras目标函数的完整列表请参考官网)如下所示。

这些目标函数平均了所有预测错误,并且如果预测远离真实值,平方运算将让该差距更加明显。

tlog(p)−(1−t)log(1−p)

该目标函数适用于二元标签预测。

该目标函数适用于多分类标签预测。它也是与激活函数softmax关联的默认选择。

一些常见的性能评估指标(Keras性能评估指标的完整列表请参考官网)如下所示。

性能评估与目标函数类似,唯一的区别是它们不用于训练模型,而只用于评估模型。 在Keras中编译模型很容易:

model.compile(loss='categorical_crossentropy', optimizer=OPTIMIZER, metrics=['accuracy'])

一旦模型编译好,就可以用fit()函数进行训练了,该函数指定了以下参数。

在Keras中训练一个模型很简单。假设我们要迭代NB_EPOCH步:

history = model.fit(X_train, Y_train,
batch_size=BATCH_SIZE, epochs=NB_EPOCH,
verbose=VERBOSE, validation_split=VALIDATION_SPLIT)

我们留出训练集的部分数据用于验证。关键的思想是我们要基于这部分留出的训练集数据做性能评估。对任何机器学习任务,这都是值得采用的最佳实践方法,我们也将这一方法应用在所有的例子中。

一旦模型训练好,我们就可以在包含全新样本的测试集上进行评估。这样,我们就可以通过目标函数获得最小值,并通过性能评估获得最佳值。

注意,训练集和测试集应是严格分开的。 在一个已经用于训练的样例上进行模型的性能评估是没有意义的。学习本质上是一个推测未知事实的过程,而非记忆已知的内容。

score = model.evaluate(X_test, Y_test, verbose=VERBOSE)
print("Test score:", score[0])
print('Test accuracy:', score[1])

恭喜,你已在Keras中定义了你的第一个神经网络。仅几行代码,你的计算机已经能识别手写数字了。让我们运行代码,并看看其性能。

让我们看看代码运行结果,如图1.7所示。

图1.7

首先,网络结构被铺开,我们可以看到使用的不同类型的网络层、它们的输出形状、需要优化的参数个数,以及它们的连接方式。之后,网络在48 000个样本上进行训练,12 000个样本被保留并用于验证。一旦构建好神经网络模型,就可以在10 000个样本上进行测试。如你所见,Keras内部使用了TensorFlow作为后端系统进行计算。现在,我们不探究内部训练细节,但我们可以注意到该程序运行了200次迭代,每次迭代后,准确率都有所提高。

训练结束后,我们用测试数据对模型进行测试,其中训练集上达到的准确率为92.36%,验证集上的准确率为92.27%,测试集上的准确率为92.22%。

这意味着10个手写数字中只有不到一个没有被正确识别。当然我们可以比这做得更好。在图1.8中,我们可以看到测试的准确率。

图1.8

现在我们有了基线精度,训练集上的准确率为92.36%,验证集上的准确率为92.27%,测试集上的准确率为92.22%,这是一个很好的起点,当然我们还能对它进行提升,我们看一下如何改进。

第一个改进方法是为我们的网络添加更多的层。所以在输入层之后,我们有了第一个具有N_HIDDEN个神经元并将ReLU作为激活函数的dense层。这一个追加层被认为是隐藏的,因为它既不与输入层也不与输出层直接相连。在第一个隐藏层之后,是第二个隐藏层,这一隐藏层同样具有N_HIDDEN个神经元,其后是一个具有10个神经元的输出层,当相关数字被识别时,对应的神经元就会被触发。以下代码定义了这个新网络。

from __future__ import print_function
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.optimizers import SGD
from keras.utils import np_utils
np.random.seed(1671) #重复性设置
#网络和训练
NB_EPOCH = 20
BATCH_SIZE = 128
VERBOSE = 1
NB_CLASSES = 10 #输出个数等于数字个数
OPTIMIZER = SGD() #优化器,本章稍后介绍
N_HIDDEN = 128
VALIDATION_SPLIT=0.2 #训练集用于验证的划分比例
#数据:混合并划分训练集和测试集数据
(X_train, y_train), (X_test, y_test) = mnist.load_data()
#X_train是60000行28×28的数据,变形为60000×784
RESHAPED = 784
#
X_train = X_train.reshape(60000, RESHAPED)
X_test = X_test.reshape(10000, RESHAPED)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
#归一化
X_train /= 255
X_test /= 255
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
#将类向量转换为二值类别矩阵
Y_train = np_utils.to_categorical(y_train, NB_CLASSES)
Y_test = np_utils.to_categorical(y_test, NB_CLASSES)
#M_HIDDEN个隐藏层
#10个输出
#最后是softmax激活函数
model = Sequential()
model.add(Dense(N_HIDDEN, input_shape=(RESHAPED,)))
model.add(Activation('relu'))
model.add(Dense(N_HIDDEN))
model.add(Activation('relu'))
model.add(Dense(NB_CLASSES))
model.add(Activation('softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer=OPTIMIZER,
metrics=['accuracy'])
history = model.fit(X_train, Y_train,
batch_size=BATCH_SIZE, epochs=NB_EPOCH,
verbose=VERBOSE, validation_split=VALIDATION_SPLIT)
score = model.evaluate(X_test, Y_test, verbose=VERBOSE)
print("Test score:", score[0])
print('Test accuracy:', score[1])

让我们运行代码并查看这一多层网络获取的结果。还不错,通过增加两个隐藏层,我们在训练集上达到的准确率为94.50%,验证集上为94.63%,测试集上为94.41%。这意味着相比之前的网络,准确率提高了2.2%。然而,我们将迭代次数从200显著减少到了20。这很好,但是我们要更进一步。

如果你想,你可以自己尝试,看看如果只添加一个隐藏层而非两个,或者添加两个以上的隐藏层结果会怎样。我把这个实验留作练习。图1.9显示了前例的输出结果。

图1.9

现在我们的基线在训练集上的准确率为94.50%,验证集上为94.63%,测试集上为94.41%。第二个改进方法很简单。我们决定在内部全连接的隐藏层上传播的值里,按dropout概率随机丢弃某些值。在机器学习中,这是一种众所周知的正则化形式。很惊奇,这种随机丢弃一些值的想法可以提高我们的性能。

from __future__ import print_function
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
from keras.utils import np_utils
np.random.seed(1671) # 重复性设置
#网络和训练
NB_EPOCH = 250
BATCH_SIZE = 128
VERBOSE = 1
NB_CLASSES = 10 #输出个数等于数字个数
OPTIMIZER = SGD() #优化器,本章稍后介绍
N_HIDDEN = 128
VALIDATION_SPLIT=0.2 #训练集用于验证的划分比例
DROPOUT = 0.3
#数据:混合并划分训练集和测试集数据
(X_train, y_train), (X_test, y_test) = mnist.load_data()
#X_train是60 000行28×28的数据,变形为60 000×784
RESHAPED = 784
#
X_train = X_train.reshape(60000, RESHAPED)
X_test = X_test.reshape(10000, RESHAPED)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
#归一化
X_train /= 255
X_test /= 255
#将类向量转换为二值类别矩阵
Y_train = np_utils.to_categorical(y_train, NB_CLASSES)
Y_test = np_utils.to_categorical(y_test, NB_CLASSES)
#M_HIDDEN个隐藏层,10个输出
model = Sequential()
model.add(Dense(N_HIDDEN, input_shape=(RESHAPED,)))
model.add(Activation('relu'))
model.add(Dropout(DROPOUT))
model.add(Dense(N_HIDDEN))
model.add(Activation('relu'))
model.add(Dropout(DROPOUT))
model.add(Dense(NB_CLASSES))
model.add(Activation('softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
optimizer=OPTIMIZER,
metrics=['accuracy'])
history = model.fit(X_train, Y_train,
batch_size=BATCH_SIZE, epochs=NB_EPOCH,
verbose=VERBOSE, validation_split=VALIDATION_SPLIT)
score = model.evaluate(X_test, Y_test, verbose=VERBOSE)
print("Test score:", score[0])
print('Test accuracy:', score[1])

让我们将代码像之前一样运行20次迭代。我们看到网络在训练集上达到了91.54%的准确率,验证集上为94.48%,测试集上为94.25%,如图1.10所示。

图1.10

注意,训练集上的准确率仍应高于测试集上的准确率,否则说明我们的训练时间还不够长。所以我们试着将训练轮数大幅增加至250,这时训练集上的准确率达到了98.1%,验证集上为97.73%,测试集上为97.7%,如图1.11所示。

图1.11

当训练轮数增加时,观察训练集和测试集上的准确率是如何增加的,这一点很有用。你可以从图1.12中看出,这两条曲线在训练约250轮时相交,而这一点后就没必要进一步训练了。

图1.12

注意,我们往往会观察到,内部隐藏层中带有随机dropout层的网络,可以对测试集中的全新样本做出更好的推测。直观地讲,你可以想象成:正因为神经元知道不能依赖于邻近神经元,它自身的能力才能更好发挥。测试时,先不加入dropout层,我们运行的是所有经过高度调整过的神经元。简而言之,要测试网络加入某些dropout功能时的表现,这通常是一种很好的方法。

我们已定义和使用了一个网络,给出网络如何训练的直观解释非常有用。让我们关注一种被称为梯度下降(Gradient Descent,GD)的流行的训练方法。想象一个含有单一变量w的一般成本函数C(w),如图1.13所示。

图1.13

梯度下降可以看成一个要从山上到山谷的背包客,山上表示成函数C,山谷表示成最小值Cmin,背包客的起点为w0。背包客慢慢移动,对每一步r,梯度就是最大增量的方向。从数学上讲,该方向就是在步r到达的点wr上求得的偏导数。因此,走相反的方向,背包客就可以向山谷移动。每一步,背包客都能在下一步之前判别步长,这就是梯度下降中讲的学习率。注意,如果步长太小,背包客就会移动得很慢;如果过大,背包客又很可能错过山谷。现在,你应该记住sigmoid是一个连续函数,并可以计算导数。可以证明sigmoid函数如下所示:

它的导数如下:

ReLU函数在点0处不可微,然而,我们可以将点0处的一阶导数扩展到整个定义域,使其为0或1。这种和点相关的ReLU函数y=max(0, x)的导数如下:

一旦我们有了导数,就可以用梯度下降技术来优化网络。Keras使用它的后端(TensorFlow或者Theano)来帮助我们计算导数,所以我们不用担心如何实现或计算它。我们只需选择激活函数,Keras会替我们计算导数。

神经网络本质上是带有几千个甚至几百万个参数的多个函数的组合。每个网络层计算一个函数,使其错误率最低,以改善学习阶段观察到的准确率。当我们讨论反向传播时,我们会发现这个最小化过程比我们的简单示例更加复杂。然而,它同样基于降至山谷的直观过程。

Keras实现了梯度下降的一个快速变体,称为随机梯度下降(Stochastic Gradient Descent,SGD),以及RMSprop和Adam这两种更先进的优化技术。除SGD具有的加速度分量之外,RMSprop和Adam还包括了动量的概念(速度分量)。这样可以通过更多的计算代价实现更快的收敛。Keras支持的优化器的完整列表请参考官网。SGD是我们到目前为止的默认选择。现在让我们尝试另外两个,这很简单,我们只需要改几行代码:

from keras.optimizers import RMSprop, Adam
...
OPTIMIZER = RMSprop() #优化器

好了,我们来进行测试,如图1.14所示。

图1.14

从图1.14可以看出,RMSprop比SDG快,因为仅在20次迭代后我们就改进了SDG,并能在训练集上达到97.97%的准确率,验证集上为97.59%,测试集上为97.84%。为完整起见,让我们看看准确率和损失函数如何随训练轮数的变化而改变,如图1.15所示。

图1.15

现在我们试试另一个优化器Adam()。这相当简单,如下:

OPTIMIZER = Adam() #优化器

正如我们所看到的,Adam稍好些。使用Adam,训练20轮后,我们在训练集上的准确率达到了98.28%,验证集上达到了98.03%,测试集上达到了97.93%,如图1.16所示。

图1.16

这是我们修改过的第5个版本,请记住我们的初始基线是92.36%。

到目前为止,我们做了渐进式的改进;然而,获得更高的准确率现在越来越难。注意,我们使用了30%的dropout概率进行优化。为完整起见,我们在选用Adam()作为优化器的条件下,测试其他dropout概率下测试集上的准确率报表,如图1.17所示。

图1.17

让我们尝试将训练中使用的轮转次数从20增加到200,不幸的是,这让我们的计算时间增加了1倍,但网络并没有任何改善。这个实验并没成功,但我们知道了即使花更多的时间学习,也不一定会对网络有所提高。学习更多的是关于采用巧妙的技术,而不是计算上花费多少时间。让我们追踪一下程序第6次修改的结果,如图1.18所示。

图1.18

另外一个我们可以进行的尝试是改变优化器的学习参数。 你可以从图1.19中看出,最优值接近0.001,这是优化器的默认学习率。不错,Adam优化器表现得非常好。

图1.19

我们还可以做另一个尝试,那就是改变内部隐藏神经元的数量。我们用不断增加的隐藏神经元汇总得出实验结果。我们可以从图1.20中看到,通过增加模型的复杂性,运行时间也显著增加,因为有越来越多的参数需要优化。然而,随着网络的增长,我们通过增加网络规模获得的收益也越来越少。

图1.20

图1.21显示了随着隐藏神经元的增多,每次迭代所需的时间。

图1.21

图1.22显示了随着隐藏神经元的增多,准确率的变化。

图1.22

对训练集中提供的所有样例,同时对输入中给出的所有特征,梯度下降都尝试将成本函数最小化。随机梯度下降开销更小,它只考虑BATCH_SIZE个样例。因此,让我们看一下改变这个参数时的效果。如图1.23所示,最优的准确率在BATCH_SIZE=128时取得。

图1.23

现在我们总结一下:使用5种不同的修改,我们可以将性能从92.36%提高到97.93%。首先,我们在Keras中定义一个简单层的网络;然后,我们通过增加隐藏层提高性能;最后,我们通过添加随机的dropout层及尝试不同类型的优化器改善了测试集上的性能。结果汇总如表1.1所示。

表1.1

模型/准确率

训练

验证

测试

Simple

92.36%

92.37%

92.22%

Two hidden(128)

94.50%

94.63%

94.41%

Dropout(30%)

98.10%

97.73%

97.7%(200次)

RMSprop

97.97%

97.59%

97.84%(20次)

Adam

98.28%

98.03%

97.93%(20次)

然而,接下来的两个实验没有显著提高。增加内部神经元的数量会产生更复杂的模型,并需要更昂贵的计算,但它只有微小的收益。即使增加训练轮数,也是同样的结果。 最后一个实验是修改优化器的BATCH_SIZE。

直观地说,良好的机器学习模型应在训练数据上取得较低的误差。在数学上,这等同于给定构建好的机器学习模型,使其在训练数据上的损失函数最小化,其公式表示如下:

min:{loss(训练数据|模型)}

然而,这可能还不够。为捕捉训练数据内在表达的所有关系,模型可能会变得过度复杂。而复杂性的增加可能会产生两个负面后果。第一,复杂的模型可能需要大量的时间来执行;第二,因其所有内在关系都被记忆下来,复杂的模型可能在训练数据上会取得优秀的性能,但在验证数据上的性能却并不好,因为对于全新的数据,模型不能进行很好的泛化。再次重申,学习更多的是关于泛化而非记忆。图1.24表示了在验证集和训练集上均呈下降的损失函数。然而,由于过度拟合,验证集上的某一点后,损失函数开始增加,如图1.24所示。

图1.24

根据经验,如果在训练期间,我们看到损失函数在验证集上初始下降后转为增长,那就是一个过度训练的模型复杂度问题。实际上,过拟合是机器学习中用于准确描述这一问题的名词。

为解决过拟合问题,我们需要一种捕捉模型复杂度的方法,即模型的复杂程度。 解决方案会是什么呢?其实,模型不过是权重向量,因此,模型复杂度可以方便地表示成非零权重的数量。换句话说,如果我们有两个模型M1和M2,在损失函数上几乎实现了同样的性能,那么我们应选择最简单的包含最小数量非零权重的模型。如下所示,我们可以使用超参数λ≥0来控制拥有简单模型的重要性:

min:{loss(训练数据|模型)}+λ*complexity(模型)

机器学习中用到了3种不同类型的正则化方法。

注意,相同的正则化方案可以独立地应用于权重、模型和激活函数。

因此,应用正则化方案会是一个提高网络性能的好方法,特别是在明显出现了过拟合的情况下。这些实验可以留给对此感兴趣的读者作为练习。

请注意,Keras同时支持L1、L2和弹性网络这3种类型的正则化方法。加入正则化方法很简单。举个例子,这里我们在内核(权重W)上使用了L2正则化方法:

from keras import regularizers model.add(Dense(64, input_dim=64, 
kernel_regularizer= regularizers.l2(0.01)))

关于可用参数的完整说明,请参见Keras官网。

上述实验让我们了解了微调网络的可能方式。 然而,对一个例子有效的方法不一定对其他例子也有效。对于给定的网络,实际上有很多可以优化的参数(如隐藏神经元的数量、BATCH_SIZE、训练轮数,以及更多关于网络本身复杂度的参数等)。

超参数调优是找到使成本函数最小化的那些参数组合的过程。关键思想是,如果我们有n个参数,可以想象成它们定义了一个n维空间,目标是找出空间中和成本函数最优值对应的点。实现此目标的一种方法是在该空间中创建一个网格,并系统地检查每个网格顶点的成本函数值。换句话说,这些参数被划分成多个桶,并且通过蛮力法来检查值的不同组合。

当网络训练好后,它就可以用于预测。在Keras中,这很简单。我们可以使用以下方法:

#计算预测
predictions = model.predict(X)

对于给定的输入,可以计算出几种类型的输出,包括以下方法。

多层感知机通过称为反向传播的过程在训练数据上学习。这是个错误一经发现就逐渐改进的过程。让我们看看它是如何工作的。

请记住,每个神经网络层都有一组相关的权重,用于确定给定输入集合的输出值。 此外,还请记住神经网络可以有多个隐藏层。

开始时,所有的权重都是随机分配的。然后,网络被训练集中的每个输入激活:权重值从输入阶段开始向前传播给隐藏层,隐藏层再向前传播给进行输出预测的输出层(注意,在简化图1.25中,我们仅用绿色虚线表示几个值,但实际上,所有值都是沿网络前向传播的)。

图1.25

由于我们知道训练集中的真实观察值,因而可以计算预测中产生的误差。回溯的关键点是将误差反向传播,并使用适当的优化器算法,如梯度下降,来调整神经网络的权重,以减小误差(同样为了简单起见,只表示出几个错误值),如图1.26所示。

图1.26

将输入到输出的正向传播和误差的反向传播过程重复几次,直到误差低于预定义的阈值。整个过程如图1.27所示。

图1.27

特征表示这里用于驱动学习过程的输入和标签。模型通过这样的方式更新,损失函数被逐渐最小化。在神经网络中,真正重要的不是单个神经元的输出,而是在每层中调整的集体权重。因此,网络以这样的方式逐渐调整其内部权重,预测正确的标签数量也跟着增多。当然,使用正确的集合特征及高质量的标签数据是在学习过程中偏差最小化的基础。

识别手写数字的同时,我们得出结论,准确率越接近 99%,提升就越困难。如果想要有更多的改进,我们肯定需要一个全新的思路。想一想,我们错过了什么?

基本的直觉是,目前为止,我们丢失了所有与图像的局部空间相关的信息。 特别地,这段代码将位图转换成空间局部性消失的平面向量:

#X_train是60000行28x28的数据,变形为60000 x 784
X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)

然而,这并非我们大脑工作的方式。 请记住,我们的想法是基于多个皮质层,每一层都识别出越来越多的结构化信息,并仍然保留了局部化信息。首先,我们看到单个的像素,然后从中识别出简单的几何形状,最后识别出更多的复杂元素,如物体、面部、人体、动物等。

在第3章“深度学习之卷积网络”中,我们将看到一种特殊类型的深度学习网络,这种网络被称为卷积神经网络(Convolutional Neural Network,CNN),它同时考虑了两个方面:既保留图像(更一般地,任何类型的信息)中空间局部性的信息, 也保留层次渐进的抽象学习的思想。一层时,你只能学习简单模式;多层时,你可以学习多种模式。 在学习CNN之前,我们需要了解Keras架构方面的内容,并对一些机器学习概念进行实用的介绍。这将是下一章的主题。

本章中,你学习了神经网络的基础知识。具体包括:什么是感知机,什么是多层感知机,如何在Keras中定义神经网络,当确立了良好的基线后如何逐步改进性能,以及如何微调超参数空间。 此外,你现在对一些有用的激活函数(sigmoid和ReLU)有了了解,还学习了如何基于反向传播算法来训练网络,如梯度下降、随机梯度下降,或更复杂的方法如Adam和RMSprop。

在下一章中,我们将学习如何在AWS、微软Azure、谷歌Cloud以及你自己的机器上安装Keras。除此之外,我们还将给出Keras API的概述。


相关图书

ChatGPT原理与应用开发
ChatGPT原理与应用开发
深度学习的数学——使用Python语言
深度学习的数学——使用Python语言
深度学习:从基础到实践(上、下册)
深度学习:从基础到实践(上、下册)
动手学深度学习(PyTorch版)
动手学深度学习(PyTorch版)
深度学习与医学图像处理
深度学习与医学图像处理
深度强化学习实战:用OpenAI Gym构建智能体
深度强化学习实战:用OpenAI Gym构建智能体

相关文章

相关课程