版权信息 书名:Python神经网络编程
ISBN:978-7-115-47481-0
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 [英] 塔里克•拉希德(Tariq Rashid)
译 林 赐
责任编辑 陈冀康
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线: (010)81055410
反盗版热线: (76010)81055315
版权声明 Simplified Chinese translation copyright ©2018 by Posts and Telecommunications Press
ALL RIGHTS RESERVED.
Make Your Own Neural Network, by Tariq Rashid, ISBN 9781530826605 Copyright © 2016 by Tariq Rashid
本书中文简体版由作者授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式或任何手段复制和传播。
版权所有,侵权必究。
内容提要 神经网络是一种模拟人脑的神经网络,以期能够实现类人工智能的机器学习技术。
本书揭示神经网络背后的概念,并介绍如何通过Python实现神经网络。全书分为3章和两个附录。第1章介绍了神经网络中所用到的数学思想。第2章介绍使用Python实现神经网络,识别手写数字,并测试神经网络的性能。第3章带领读者进一步了解简单的神经网络,观察已受训练的神经网络内部,尝试进一步改善神经网络的性能,并加深对相关知识的理解。附录分别介绍了所需的微积分知识和树莓派知识。
本书适合想要从事神经网络研究和探索的读者学习参考,也适合对人工智能、机器学习和深度学习等相关领域感兴趣的读者阅读。
译者序 渥太华的八月,不像中国的南方那么炎热,甚至有丝丝凉意。每到下午时分,如果没有下雨,工作了一天,有些倦怠的我一般会沿着里多运河(世界文化遗产),朝着国会山的方向慢慢跑去。从出租屋到里多运河,不到10分钟的路程。来到运河前,生命就像翻开了一页流畅缠绵的琴谱,一群白鸽在空阔悠远的蓝天下舞蹈,偶尔,还可以听到为数不多的几只夏蝉在悠久的运河边轻轻吟唱,不是那么刺目的阳光随意地拨动闪着灵光的水面,凭栏远眺,里多运河就像一位饱经风霜的老人,向周围的人们娓娓诉说着它的前世今生……
日子就这样一天一天重复着,连续数月,我完成了此书的翻译。人工智能、神经网络、机器学习……一个一个富有现代电子气息的词汇,一次又一次给我的大脑带来新的感受,也给我带来了对人生的新理解,但是,越是如此,我就越想回到历史寻找答案,希望在历史的废墟中,能找到只言片语,解开我心中的疑惑。
多年来,普通人(包括我在内)对人工智能有一个误区,即人工智能只不过是用更高级、更复杂的数学指令,告诉计算机怎么做,怎样模拟人类行为,让计算机“佯装”理解人类的感情。但是,本书的作者告诉我们,其实,授“计算机”以鱼不如授“计算机”以渔。无需太高深的数学思想,我们仅凭高中数学,就可以打造出一个专家级别的“神经网络”。这并非夸大其辞,危言耸听,而是真真切切、实实在在的事实。
现在,各大报纸、网站、各式各样的自媒体,都在宣称一种观点,就是告诫青少年好好学习,否则将来不好找工作。我以为,这种观点还太乐观了,这误导了读者,认为只要现在努力学习,就可以顺利“逆袭”。如果用有点烧脑、学究式的语言来描述这个问题,一言以蔽之,那就是“人工智能时代存在一个人类价值体现方式变革的问题”。换句话说,如果我们依旧指望课本里的那些知识求生存,不求创新,不求探索,那么对知识掌握得再好,也只是拾人牙慧,只能湮没于滚滚的历史车轮之下。如果你想知道,我为何有如此感叹,请仔细阅读本书。只要你有一点中学的数学基础,看得懂中文,而对计算又有那么一点兴趣,你就可以读懂本书。逻辑的基础其实很简单。
在这里,要特别感谢人民邮电出版社的领导和编辑,感谢他们对我的信任和理解,把这样一本好书交给我翻译。同时我也要感谢他们为本书的出版投入了巨大的热情,可谓呕心沥血。没有他们的耐心和帮助,本书不可能顺利付梓。
译者才疏学浅,见闻浅薄,译文多有不足甚至错漏之处,还望读者谅解并不吝指正。读者如有任何意见和建议,请将反馈信息发送到邮箱cilin2046@gmail.com,不胜感激。
林赐
2017年9月15日
于加拿大渥太华大学
序言 探索智能机器 千百年来,人类试图了解智能的机制,并将它复制到思维机器上。
人类从不满足于让机械或电子设备帮助做一些简单的任务,例如,使用燧石打火,使用滑轮吊起沉重的岩石,使用计算器做算术。
相反,我们希望能够自动化执行更具有挑战性、相对复杂的任务,如对相似的照片进行分组、从健康细胞中识别出病变细胞,甚至是来一盘优雅的国际象棋博弈。这些任务似乎需要人类的智能才能完成,或至少需要人类思维中的某种更深层次、更神秘的能力来完成,而在诸如计算器这样简单的机器中是找不到这种能力的。
具有类似人类智能的机器是一个如此诱人且强大的想法,我们的文化对它充满了幻想和恐惧,如斯坦利·库布里克导演的《2001: A Space Odyssey》中的HAL 9000(拥有巨大的能力却最终给人类带来了威胁)、动作片中疯狂的“终结者(Terminator)”机器人以及电视剧《Knight Rider》中具有冷静个性的话匣子KITT汽车。
1997年,国际象棋卫冕世界冠军、国际象棋特级大师加里·卡斯帕罗夫被IBM“深蓝”计算机击败,我们在庆祝这一历史性成就的同时,也担心机器智能的潜力。
我们如此渴望智能机器,以至于一些人受到了诱惑,使用欺骗手段,例如,臭名昭著的国际象棋机器Turkey仅仅是将一个人隐藏在机柜内而已!
人工智能的新黄金时代 在20世纪50年代,人工智能这门学科正式成立,此时,人类雄心勃勃,对人工智能抱着非常乐观的态度。最初的成功,让人们看到了计算机可以进行简单的博弈、证明定理,因此,一些人相信,在十年左右的时间内,人类级别的人工智能将会出现。
但是,实践证明:发展人工智能困难重重,进展一度停滞不前。20世纪70年代,人们在学术界挑战人工智能的雄心遭到了毁灭性的打击。接下来,人们削减了人工智能研究经费,对人工智能的兴趣消失殆尽。
机器那冰冷的逻辑,绝对的1和0,看起来似乎永远不能够实现细致入微的、有机的,有时甚至模糊的生物大脑思维过程。
在一段时间内,人类未能独具匠心,百尺竿头,更进一步,将机器智能探索带出其既定轨迹。在此之后,研究人员灵光一现,研究人员灵光一现,为什么不模仿天然生物大脑的工作机制来构建人工大脑?真正的大脑具有神经元,而不是逻辑门。真正人脑具有更优雅、更有机的推理,而不是冰冷的、非黑即白的、绝对的传统算法。
蜜蜂或鸽子大脑的简单性与其能够执行复杂任务的巨大反差,这一点启发了科学家。就是这零点几克的大脑,看起来就能够做许多事情,如导航、适应风向、识别食物和捕食者、快速地决定是战斗还是逃跑。当今的计算机拥有大量的廉价资源,能够模仿和改进这些大脑吗?一只蜜蜂大约有950 000个神经元,今天的计算机,具有G比特和T比特的资源,能够表现得比蜜蜂更优秀吗?
但是,如果使用传统的方法来求解问题,那么即使计算机拥有巨大的存储和超快的处理器,也无法实现鸟和蜜蜂使用相对微小的大脑所做的事情。
受到仿生智能计算的驱动,神经网络(Neural Network)出现了,并且神经网络从此成为在人工智能领域中最强大、最有用的方法之一。今天,谷歌的Deepmind以神经网络为基础,能够做一些非常奇妙的事情,如让计算机学习如何玩视频游戏,并且在人类历史上第一次在极其变化多端的围棋博弈中击败了世界级的大师。如今,神经网络已经成为了日常技术的核心,例如自动车牌号码识别、解码手写的邮政编码。
本书所探讨的就是神经网络,让你了解神经网络如何工作,帮你制作出自己的神经网络,训练神经网络来识别人类的手写字符。如果使用传统的方法来执行这个任务,那么将是非常困难的。
前言 本书的目标读者 本书是为了任何希望了解什么是神经网络的读者而编写的,是为了任何希望设计和使用自己神经网络的读者而编写的,也是为了任何希望领略那些在神经网络发挥核心作用、相对容易但激动人心的数学思想的读者而编写的。
本书的目标读者,不是数学或计算机科学方面的专家。你不需要任何专业知识或超出中学的数学能力。
如果你可以进行加、减、乘、除运算,那么你就可以制作自己的神经网络。我们使用的最困难运算是梯度演算(gradient calculus),但是,我们会对这一概念加以说明,使尽可能多的读者能够理解这个概念。
有兴趣的读者,不妨以本书为起点,进一步探索激动人心的人工智能。一旦你掌握了神经网络的基本知识,你就可以将神经网络的核心思想运用到许多不同的问题中。
教师可以使用本书,优雅从容地解释神经网络,解释神经网络的实现,激起学生对神经网络的热情,鼓励学生使用短短的几行代码制作出能够学习的人工智能。本书中的代码已经通过了测试,能够在物美价廉的计算机——树莓派上工作。树莓派是备受学校和青年学生欢迎的一款计算机。
当我年少的时候,我难以理解这些功能强大但神秘的神经网络是如何工作的。当时,我多么希望存在一本类似的书籍。我在各种书籍、电影和杂志中看到关于神经网络的只言片语,但是当时,我只能找到一些艰深难懂的教科书,而这些教科书是为那些对数学及其术语非常了解的专家级别的人而编写的。
我曾经希望有人能够以让中学生理解的方式向我解释神经网络,满足我的好奇心。而这就是我写作本书的目的。
我们将会做些什么 在这本书中,我们将扬帆起航,制作神经网络,识别手写数字。
我们将从非常简单的预测神经元开始,然后逐步改进它们,直到达到它们的极限。顺着这条路,我们将做一些短暂的停留,学习一些数学概念。我们需要这些数学概念来理解神经网络如何学习和预测问题的解。
我们将浏览一些数学思想,如函数、简单的线性分类器、迭代细化、矩阵乘法、梯度演算、通过梯度下降进行优化,甚至是几何旋转。但是,所有这些数学概念将会以一种非常优雅清晰的方式进行解释,并且除了简单的中学数学知识以外,读者完全不需要任何前提知识或专业技术。
一旦我们成功制作了第一个神经网络,我们将带着这种思想,在各个方面使用这种思想。例如,我们无需诉诸额外的训练数据,就可以使用图像处理来改善机器学习。我们将一窥神经网络的思想,看看它是否揭示了任何深刻的见解——很多书籍并没有向你展示神经网络的工作机制。
当我们循序渐进制作神经网络时,我们还将学习一种非常简单、有用和流行的编程语言Python。同样,你不需要有任何先前的编程经验。
我们将如何做到这点 本书的主要目的是向尽可能多的人揭示神经网络背后的概念。这意味着我们将一直从让人们感觉舒服和熟悉的地方开始介绍这些概念。我们将采用简单的步骤,小步前进,从一些安全的地方开始构建知识,直到我们拥有足够的知识,去理解和欣赏一些关于神经网络的、很酷炫或让人很兴奋的东西。
为了使事情尽可能顺畅方便,我们将抵制诱惑,将讨论范围严格限定为制作神经网络所必需的知识。一些读者可能会对一些有趣的题外话感兴趣,如果你是这样的读者,那么我们鼓励你对神经网络进行更广泛的研究。
本书不会探讨所有可能的神经网络优化和改进的方法。虽然在实践中,存在很多种优化和改进的方法,但是这些内容与本书的核心目的背道而驰,本书只是想用一种尽可能简单易懂、简洁明了的方式介绍神经网络的基本思路。
我们有意将本书分成3章:
在第1章中,我们将如清风拂面般,一览在简单的神经网络中所用的数学思想。我们有意不介绍任何计算机编程知识,以避免喧宾夺主地干扰了本书的核心思想。
在第2章中,我们将学习足以实现自己的神经网络的Python知识。我们将训练神经网络,识别手写数字,并且会测试神经网络的性能。
在第3章中,我们将进一步了解简单的神经网络,这超出了了解基本神经网络知识的范畴,但是我们这样做只是为了获得一些乐趣。我们将尝试一些想法,进一步改善神经网络的性能,我们将观察已受训练的神经网络内部,看看我们是否理解神经网络所学习到的知识,是否理解神经网络是如何做出决定进行回答的。
我们使用的软件工具都是免费开源的,你无须支付任何费用。你也不需要一台昂贵的计算机制作自己的神经网络。本书中的所有代码都已经经过了测试,可以在价廉物美的树莓派Zero上运行。在本书的末尾,附录B介绍了如何让你的树莓派准备就绪。
反馈 如果在数学和计算机科学方面,我没能给你一种真正的兴奋和惊喜的感觉,那么这是我的失败。
如果在通过制作自己的人工智能、模拟人类大脑的学习能力的过程中,我没能向你展示出中学数学和简单的计算机方法可以变得如此出神入化,那么这是我的失败。
如果我没能给你信心和愿望,进一步探索那无比丰富的人工智能领域,那么这是我的失败。
我欢迎任何改善本书的反馈。请通过电子邮件地址makeyourownneuralnetwork@gmail.com或推特@myoneuralnet与我联系。
你也可以在异步社区(www.epubit.com),找到本书页面并下载示例代码。在这个网页中,也有中译本经过确认的勘误。
第1章 神经网络如何工作 “从你身边所有的小事情中,找到灵感。”
1.1 尺有所短,寸有所长 计算机的核心部分就是计算器。这些计算器做算术非常快。
对于执行与计算器相匹配的任务而言,如对数字进行相加算出销售额、运用百分比算出税收、绘制现存数据的图表,这是很不错的。
即使是在计算机上观看网络电视节目或听流媒体的音乐,也只涉及一次又一次地执行简单的算术指令。在互联网上通过管道将1和0输送到计算机,重建视频帧,所使用的算术也不会比你在中学所做的加法运算复杂,这一点也许令你颇为惊奇。
计算机可以以相当快的速度,在1秒钟内进行4位数甚至10位数的相加,这也许给人留下了深刻的印象,但是这不是人工智能。人类可能发现自己很难快速地进行加法运算,然而进行加法运算的过程不需要太多的智慧。简单说来,这只要求计算机拥有遵循基本指令的能力,而这正是计算机内的电子器件所做的事情。
现在,让我们转到事情的背面,掀开计算机的底牌。
让我们观察下面的图片,看看你能认出图片中包含哪些内容。
你和我都看到了人脸、猫和树的图片,并识别出了这些内容。事实上,我们可以以非常高的精确度快速地做到这一点。在这方面,我们通常不会出错。
我们可以处理图像中所包含的相当大量的信息,并且可以成功地识别图像中有哪些内容。但这种任务对计算机而言,并不是那么容易,实际上,是相当困难的。
问题
计算机
人类
快速地对成千上万的大数字进行乘法运算
简单
困难
在一大群人的照片中查找面孔
困难
简单
我们怀疑图像识别需要人类智能,而这是机器所缺乏的。无论我们造出的机器多么复杂和强大,它们依然不是人类。但是,由于计算机速度非常快,并且不知疲倦,我们恰恰希望计算机能更好地进行求解图像识别这类问题。人工智能所探讨的一切问题就是解决这种类型的难题。
当然,计算机将永远使用电子器件制造,因此研究人工智能的任务就是找到新方法或新算法,使用新的工作方式,尝试求解这类相对困难的问题。即使计算机不能完美地解决这些问题,但是我们只要求计算机足够出色,给人们留下一种印象,让人觉得这是智能在起作用。
关键点
有些任务,对传统的计算机而言很容易,对人类而言却很难。例如,对数百万个数字进行乘法运算。
另一方面,有些任务对传统的计算机而言很难,对人类而言却很容易。例如,从一群人的照片中识别出面孔。
1.2 一台简单的预测机 让我们先从构建超级简单的机器开始。
想象一下,一台基本的机器,接受了一个问题,做了一些“思考”,并输出了一个答案。与我们在上面的例子中进行的操作一样,我们从眼睛输入图片,使用大脑分析场景,并得出在场景中有哪些物体的结论。
下面就是这台机器看起来的样子。
记住,计算机不是真的思考,它们只是得到包装的计算器,因此让我们使用更恰当的词语来形容这个过程。
一台计算机接受了一些输入,执行了一些计算,然后弹出输出。下列的内容详细说明了这一点。一台计算机对“3×4”的输入进行处理,这种处理也许是将乘法运算转化为相对简单的一组加法,然后弹出答案“12”。
你可能会想“这也没什么了不起的吧!”,没关系。这里,我们使用简单和熟悉的例子来引出此后我们将看到的更有趣的神经网络的概念。
让我们稍微增加一点复杂度。
试想一下将千米转化为英里的一台机器,如下所示。
现在想象一下,我们不知道千米和英里之间的转换公式。我们所知道的就是,两者之间的关系是线性的。这意味着,如果英里数加倍,那么表示相同距离的千米数也是加倍的。这是非常直观的。如果这都不是真理,那么这个宇宙就太让人匪夷所思了。
千米和英里之间的这种线性关系,为我们提供了这种神秘计算的线索,即它的形式应该是“英里=千米×C”,其中C为常数。现在,我们还不知道这个常数C是多少。
我们拥有的唯一其他的线索是,一些正确的千米/英里匹配的数值对示例。这些示例就像用来验证科学理论的现实世界观察实验一样,显示了世界的真实情况。
真实示例
千米
英里
1
0
0
2
100
62.137
我们应该做些什么,才能计算出缺失的常数C呢?我们信手拈来一个随机的数值,让机器试一试!让我们试着使用C = 0.5,看看会发生什么情况。
这里,我们令:英里=千米×C,其中千米为100,当前,我们猜测C为0.5。
这台机器得到50英里的答案。
嗯,鉴于我们随机选择了C = 0.5,这种表现还算不错。但是,编号为2的真实示例告诉我们,答案应该是62.137,因此我们知道这是不准确的。
我们少了12.137。这是计算结果与我们列出的示例真实值之间的差值,是误差。即:
误差值=真实值-计算值
= 62.137-50
= 12.137
下一步,我们将做些什么呢?我们知道错了,并且知道差了多少。我们无需对这种误差感到失望,我们可以使用这个误差,指导我们得到第二个、更好的C的猜测值。
再看看这个误差值。我们少了12.137。由于千米转换为英里的公式是线性的,即英里= 千米×C,因此我们知道,增加C就可以增加输出。
让我们将C从0.5稍微增加到0.6,观察会发生什么情况。
现在,由于将C设置为0.6,我们得到了英里=千米×C = 100×0.6 = 60,这个答案比先前50的答案更好。我们取得了明显的进步。
现在,误差值变得更小了,为2.137。这个数值甚至可能是我们很乐于接受的一个误差值。
这里,很重要的一点是,我们使用误差值的大小指导如何改变C的值。我们希望输出值从50增大一些,因此我们稍微增加了C的值。
我们不必尝试使用代数法计算出C需要改变的确切量,让我们继续使用这种方法改进C值。如果你还不能被我说服,还是认为计算出确切的答案才够简单,那么,请记住,更多有趣的问题是没有一个简单的数学公式将输出和输入关联起来的。这就是我们需要诸如神经网络这样相对成熟而复杂的方法的原因。
让我们再次重复这个过程。输出值60还是太小了。我们再次微调C,将其从0.6调到0.7。
糟糕!过犹不及,结果超过了已知的正确答案。先前的误差值为2.137,现在的误差值为-7.863。这个负号告诉我们,我们不是不足,而是超调了。请记住上面的公式,误差值等于真实值减去计算值。
如此说来,C = 0.6比C = 0.7好得多。我们可以就此结束这个练习,欣然接受C = 0.6带来的小小误差。但是,让我继续向前走一小段距离。我们为什么不使用一个较小的量,微调C,将C从0.6调到0.61呢?
这比先前得到的答案要好得多。我们得到输出值61,比起正确答案62.137,这只差了1.137。
因此,最后的这次尝试告诉我们,应该适度调整C值。如果输出值越来越接近正确答案,即误差值越来越小,那么我们就不要做那么大的调整。使用这种方式,我们就可以避免像先前那样得到超调的结果。
同样,读者无需为如何使用确切的方式算出C值而分心,请继续关注这种持续细化误差值的想法,我们建议修正值取误差值的百分之几。直觉上,这是正确的:大误差意味着需要大的修正值,小误差意味着我们只需要小小地微调C的值。
无论你是否相信,我们刚刚所做的,就是走马观花地浏览了一遍神经网络中学习的核心过程。我们训练机器,使其输出值越来越接近正确的答案。
这值得读者停下来,思考一下这种方法,我们并未像在学校里求解数学和科学问题时所做的一样一步到位,精确求解问题。相反,我们尝试得到一个答案,并多次改进答案,这是一种非常不同的方法。一些人将这种方法称为迭代,意思是持续地、一点一点地改进答案。
关键点
所有有用的计算机系统都有一个输入和一个输出,并在输入和输出之间进行某种类型的计算。神经网络也是如此。
当我们不能精确知道一些事情如何运作时,我们可以尝试使用模型来估计其运作方式,在模型中,包括了我们可以调整的参数。如果我们不知道如何将千米转换为英里,那么我们可以使用线性函数作为模型,并使用可调节的梯度值作为参数。
改进这些模型的一种好方法是,基于模型和已知真实示例之间的比较,得到模型偏移的误差值,调整参数。