- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
深度学习与神经网络
展开查看详情
1 .神经⽹络与深度学习 Neural Networks and Deep Learning (美)Michael Nielsen 著 Xiaohu Zhu 译 Freeman Zhang June 8, 2017 Version: 0.5
2 .版权 本书英⽂原版地址为:http://neuralnetworksanddeeplearning.com/ 。 在学术著作中请引⽤英⽂原⽂为:Michael A. Nielsen, “Neural Networks and Deep Learning”, Determination Press, 2015。 英⽂版及本书采⽤ Creative Commons Attribution-NonCommercial 3.0 Unported License 许 可协议。这意味着你可以⾃由地拷⻉、分发、扩展本书内容,但不得出售。如果你对商业⽤途感 兴趣,英⽂版请联系作者,中⽂版请联系翻译团队。 i
3 .⽬录 版权 i ⽬录 ii 关于作者 iv 关于本书翻译 v 前⾔ vi 这本书是关于什么的? vii 关于练习和问题 ix 1 使⽤神经⽹络识别⼿写数字 1 1.1 感知机 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 S 型神经元 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 1.3 神经⽹络的架构 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.4 ⼀个简单的分类⼿写数字的⽹络 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.5 使⽤梯度下降算法进⾏学习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.6 实现我们的⽹络来分类数字 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.7 迈向深度学习 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2 反向传播算法如何⼯作 34 2.1 热⾝:神经⽹络中使⽤矩阵快速计算输出的⽅法 . . . . . . . . . . . . . . . . . . . 34 2.2 关于代价函数的两个假设 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 2.3 Hadamard 乘积,s ⊙ t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.4 反向传播的四个基本⽅程 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 2.5 四个基本⽅程的证明(可选) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 2.6 反向传播算法 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 2.7 代码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 2.8 在哪种层⾯上,反向传播是快速的算法? . . . . . . . . . . . . . . . . . . . . . . 45 2.9 反向传播:全局观 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3 改进神经⽹络的学习⽅法 50 3.1 交叉熵代价函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 ii
4 . ⽬录 3.1.1 引⼊交叉熵代价函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 3.1.2 使⽤交叉熵来对 MNIST 数字进⾏分类 . . . . . . . . . . . . . . . . . . . . 60 3.1.3 交叉熵的含义?源⾃哪⾥? . . . . . . . . . . . . . . . . . . . . . . . . . . 61 3.1.4 柔性最⼤值 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 3.2 过度拟合和正则化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 3.2.1 正则化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 3.2.2 为何正则化可以帮助减轻过度拟合 . . . . . . . . . . . . . . . . . . . . . . 75 3.2.3 正则化的其他技术 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 3.3 权重初始化 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 3.4 再看⼿写识别问题:代码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 3.5 如何选择神经⽹络的超参数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 3.6 其它技术 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 3.6.1 随机梯度下降的变化形式 . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 3.6.2 ⼈⼯神经元的其他模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 3.6.3 有关神经⽹络的故事 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111 4 神经⽹络可以计算任何函数的可视化证明 113 4.1 两个预先声明 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 4.2 ⼀个输⼊和⼀个输出的普遍性 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 4.3 多个输⼊变量 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126 4.4 S 型神经元的延伸 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 4.5 修补阶跃函数 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 4.6 结论 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139 5 深度神经⽹络为何很难训练 140 5.1 消失的梯度问题 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 5.2 什么导致了消失的梯度问题?深度神经⽹络中的梯度不稳定性 . . . . . . . . . . . 148 5.3 在更加复杂⽹络中的不稳定梯度 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151 5.4 其它深度学习的障碍 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 6 深度学习 153 6.1 介绍卷积⽹络 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 6.2 卷积神经⽹络在实际中的应⽤ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161 6.3 卷积⽹络的代码 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 6.4 图像识别领域中的近期进展 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 6.5 其他的深度学习模型 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 6.6 神经⽹络的未来 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 A 是否有关于智能的⼀个简单的算法? 191 B 致谢 196 C 修订历史 197 中英对照术语表 198 iii
5 .关于作者 Michael Nielsen 是⼀位量⼦物理学家、科学作家、计算机编程研 究⼈员。 你可以在其主⻚ http://michaelnielsen.org/ 了解更多信息。 iv
6 .关于本书翻译 开放源码项⽬ 这本书最初是我学习 Neural Networks and Deep Learning 时做的中⽂笔记,因为原书中有 很多数学公式,所以我⽤ LATEX 来编写和排版,并将所有 LATEX 源码放置在 GitHub。其中部 分内容取⾃ Xiaohu Zhu 已经完成的翻译来避免重复的⼯作。 第三、第四章的部分内容和原⽂略有不同。原⽂中这两章的部分图形提供了交互式的形式, 而在这本中⽂版中则全部换成了静态图形。你可以在原⽂⽹⻚上试试调节对应图像的可操作的 参数加深理解,但仅阅读中⽂版本也不会有任何障碍。 如果你对此中译本有任何建议和意⻅,欢迎以 issue 的⽅式提交到 GitHub 项⽬主⻚。 —— Freeman Zhang 翻译团队 本书由以下⼈员翻译及整理: • Xiaohu Zhu:翻译第⼆、三、五、六章、附录内容。 • Freeman Zhang:(正在)翻译其余章节、补充缺失内容、校对、整理及排版。 • 感谢以下贡献者参与校对: haria yaoqingyuan lzjqsdd allenwoods yangbenfa timqian jiefangxuanyan 已知问题 请在 GitHub 项⽬的 Issues ⻚⾯查阅已知的翻译问题。 v
7 .前⾔ 《神经⽹络和深度学习》是⼀本免费的在线书。本书会教会你: • 神经⽹络,⼀种美妙的受⽣物学启发的编程范式,可以让计算机从观测数据中进⾏学习 • 深度学习,⼀个强有⼒的⽤于神经⽹络学习的众多技术的集合 神经⽹络和深度学习⽬前给出了在图像识别、语⾳识别和⾃然语⾔处理领域中很多问题的最 好解决⽅案。本书将会教你在神经⽹络和深度学习背后的众多核⼼概念。 想了解本书选择的观点的更多细节,请看这⾥。或者直接跳到第⼀章开始你们的旅程。 vi
8 .这本书是关于什么的? 神经⽹络是有史以来发明的最优美的编程范式之⼀。在传统的编程⽅法中,我们告诉计算机 做什么,把⼤问题分成许多小的、精确定义的任务,计算机可以很容易地执⾏。相⽐之下,在神 经⽹络中,我们不告诉计算机如何解决我们的问题。相反,它从观测数据中学习,找出它⾃⼰的 解决问题的⽅法。 从数据中⾃动学习,听上去很有前途。然而,直到 2006 年,除了⽤于⼀些特殊的问题,我 们仍然不知道如何训练神经⽹络去超越传统的⽅法。2006 年,被称为 “深度神经⽹络” 的学习 技术的发现引起了变⾰。这些技术现在被称为 “深度学习”。它们已被进⼀步发展,今天深度神 经⽹络和深度学习在计算机视觉、语⾳识别、⾃然语⾔处理等许多重要问题上都取得了显著的 性能。他们正被⾕歌、微软、Facebook 等公司⼤规模部署。 这本书的⽬的是帮助你掌握神经⽹络的核⼼概念,包括现代技术的深度学习。在完成这本书 的学习之后,你将使⽤神经⽹络和深度学习来解决复杂模式识别问题。你将为使⽤神经⽹络和 深度学习打下基础,来攻坚你⾃⼰设计中碰到的问题。 ⼀个以原理为导向的⽅法 本书⼀个坚定的信念,是让读者更好地去深刻理解神经⽹络和深度学习,而不是像⼀张冗⻓ 的洗⾐单⼀样模糊地列出⼀堆想法。如果你很好理解了核⼼理念,你就可以很快地理解其他新 的推论。⽤编程语⾔对⽐,把这理解为掌握⼀种新语⾔的核⼼语法、库和数据结构。你可能仍然 只是 “知道” 整个编程语⾔的⼀小部分—许多编程语⾔有巨⼤的标准库—但新的库和数据结构可 以很快且容易被理解。 这就意味着这本书的重点不是作为⼀个如何使⽤⼀些特定神经⽹络库的教程。如果你主要想 围绕着某个程序库的⽅式去学习,那不要读这本书!找到你想学习的程序库,并通过教程和⽂ 档来完成。注意这点。虽然这也许能很快解决你的问题,但是,如果你想理解神经⽹络中究竟发 ⽣了什么,如果你想要了解今后⼏年都不会过时的原理,那么只是学习些热⻔的程序库是不够 的。你需要领悟让神经⽹络⼯作的原理。技术来来去去,但原理是永恒的。 ⼀个动⼿实践的⽅法 我们将通过攻克⼀个具体的问题:教会计算机识别⼿写数字的问题,来学习神经⽹络和深度 学习的核⼼理论。这个问题⽤常规的⽅法来编程解决是⾮常困难的。然而,正如我们所看到的, 它可以很好地利⽤⼀个简单的神经⽹络来解决,只需⼏⼗⾏代码,没有特别的库。更多的是,我 们会通过多次迭代来改进程序,逐步融⼊神经⽹络和深度学习的核⼼思想。 这⼀动⼿的⽅法意味着你需要⼀些编程经验来阅读这本书。但你不必是⼀个专业的程序员。 我⽤ Python(2.7 版)写了代码,即使你不是⽤ Python 编程,努⼒⼀下也应该很容易理解。通 vii
9 .过这本书,我们将开发⼀个小的神经⽹络库,它可以⽤来实验和建⽴理解。所有的代码都可以 在这⾥下载。⼀旦你完成了这本书,或者你读它,你可以轻松地学会⼀个功能更加完善的神经 ⽹络库⽤于⽣产。 类似地,对读者数学知识的需求是适度的。在⼤多数章节中都有⼀些数学,但它通常只是初 等代数和函数图,我期望⼤多数读者都能看懂。我偶尔会使⽤更⾼级的数学,但已经组织了材 料,这样即使你理解不了有些数学细节,你还是可以跟上。使⽤数学较多的是第⼆章,其中需要 ⼀些多元微积分和线性代数。如果你不熟悉它们,我在第⼆章开始讨论了如何通览本书⽤到的 数学。如果你发现它真的很难,你可以直接跳到那⼀章的主要结果的总结。⽆论如何,不要⼀开 始就担⼼这点。 难得有⼀本书能兼顾理论和动⼿实践。但是我相信,如果我们建⽴了神经⽹络的基本思路, 你会学到最好的。我们将开发实际能⽤的代码,而不仅仅是抽象的理论,这些代码你可以探索 和扩展。这样你就可以理解其基础,不论是理论还是实践,并且扩展和提⾼你的知识⾯。 viii
10 .关于练习和问题 对科技类书籍来说,作者嘱咐读者必需做些练习和问题的情况并不少⻅。当我读到这样的警 告时,我总觉得有点奇怪。如果我不做这些练习和问题,会不会有什么不好的事情发⽣?当然不 是。我会获得⼀些时间,但抵消了理解的深度。有时,这是值得的。有时不。 所以这本书值得做什么?我的建议是你真的应该尝试⼤部分的练习,你也可以不去做⼤部分 的问题。 你应该做⼤部分的练习,因为它们对你是否理解这些材料做了基本的检查。如果你不能很容 易地解决⼀个练习,你可能错过了⼀些基本的东西。当然,如果你偶尔被困在⼀个练习上,继续 往前,你可能只是对你看到的部分有些小的误解,也许我的措辞有差。但是如果你需要挣扎于 ⼤多数练习,那么你可能需要重读⼀些早期的材料。 问题是另⼀⽅⾯。他们⽐练习更难,你很可能会努⼒去解决⼀些问题。这会有些恼⼈,但是, 当然,⾯对此种⽆奈忍耐是真正理解和内化问题的唯⼀途径。 这样⼀说,我不建议完成所有的问题。更好的是找到⾃⼰的项⽬。也许你想⽤神经⽹络来分 类你的⾳乐收藏。或预测股票价格。或是别的。但找到⼀个你关⼼的项⽬。然后你就可以忽略这 本书中的问题,或者把它们简单地应⽤在你⾃⼰的项⽬上⼯作。完成再多数量的问题,也不如 为⼀个你关⼼的项⽬奋⽃而学得多。投⼊情感是精通技艺的关键。 当然,你可能不会有这样⼀个项⽬,⾄少在当前。那很好。完成这些问题,会激发你继续努 ⼒。并⽤这本书中的素材来帮助你寻找个⼈创新项⽬的创意。 ix
11 .第1章 使⽤神经⽹络识别⼿写数字 ⼈类视觉系统是世界上众多奇迹之⼀。看看下⾯的⼿写数字序列: ⼤多数⼈毫不费⼒就能够认出这些数字为 504192。这么容易反而让⼈觉着迷惑了。在⼈类的 每个脑半球中,有着⼀个初级视觉⽪层,常称为 V1,包含 1 亿 4 千万个神经元及数百亿条神经 元间的连接。但是⼈类视觉不是就只有 V1,还包括整个视觉⽪层 —— V2、V3、V4 和 V5 —— 他们逐步地进⾏更加复杂的图像处理。⼈类的头脑就是⼀台超级计算机,通过数⼗亿年的进化 不断地演变,最终能够极好地适应理解视觉世界的任务。识别⼿写数字也不是⼀件简单的事。尽 管⼈类在理解我们眼睛展⽰出来的信息上⾮常擅⻓,但⼏乎所有的过程都是⽆意识地。所以,我 们通常并不能体会⾃⾝视觉系统解决问题的困难。 如果你尝试写出计算机程序来识别诸如上⾯的数字,就会明显感受到视觉模式识别的困难。 看起来⼈类⼀下⼦就能完成的任务变得特别困难。关于我们识别形状 —— “9 顶上有⼀个圈, 右下⽅则是⼀条竖线”这样的简单直觉 —— 实际上算法上就很难轻易表达出来了。而在你试着 让这些识别规则越发精准时,就会很快陷⼊各种混乱的异常或者特殊情形的困境中。看起来毫 ⽆希望。 神经⽹络以另⼀种⽅式看待这个问题。其主要思想是获取⼤量的⼿写数字,常称作训练样本, 然后开发出⼀个可以从这些训练样本中进⾏学习的系统。换⾔之,神经⽹络使⽤样本来⾃动 推断出识别⼿写数字的规则。另外,通过增加训练样本的数量,⽹络可以学到更多关于⼿写数 1
12 . 1.1. 感知机 字的知识,这样就能够提升⾃⾝的准确性。所以,上⾯例⼦中我们只是展出了 100 个训练数字 样本,而通过使⽤数千或者数百万或者数⼗亿的训练样本我们也许能够得到更好的⼿写数字识 别器。 本章我们将实现⼀个可以识别⼿写数字的神经⽹络。这个程序仅仅 74 ⾏,不使⽤特别的神 经⽹络库。然而,这个短小的⽹络不需要⼈类帮助便可以超过 96% 的准确率识别数字。而且, 在后⾯的章节,我们会发展出将准确率提升到 99% 的技术。实际上,最优的商业神经⽹络已经 ⾜够好到被银⾏和邮局分别⽤在账单核查和识别地址上了。 ⼿写识别常常被当成学习神经⽹络的原型问题,因此我们聚焦在这个问题上。作为⼀个原型, 它具备⼀个关键点:挑战性 —— 识别⼿写数字并不轻松 —— 但也不会难到需要超级复杂的解决 ⽅法,或者超⼤规模的计算资源。另外,这其实也是⼀种发展出诸如深度学习更加⾼级的技术 的⽅法。所以,整本书我们都会持续地讨论⼿写数字识别问题。本书后⾯部分,我们会讨论这些 想法如何⽤在其他计算机视觉的问题或者语⾳、⾃然语⾔处理和其他⼀些领域中。 当然,如果仅仅为了编写⼀个计算机程序来识别⼿写数字,本章的内容可以简短很多!但前 进的道路上,我们将扩展出很多关于神经⽹络的关键的思想,其中包括两个重要的⼈⼯神经元 (感知机和 S 型神经元) ,以及标准的神经⽹络学习算法,即随机梯度下降算法。⾃始⾄终,我专 注于解释事情的原委,并构筑你对神经⽹络的直观感受。这需要⼀个漫⻓的讨论,而不是仅仅 介绍些基本的技巧,但这对于更深⼊的理解是值得的。作为收益,在本章的最后,我们会准备好 了解什么是深度学习,以及它为什么很重要。 1.1 感知机 什么是神经⽹络?⼀开始,我将解释⼀种被称为感知机的⼈⼯神经元。感知机在 20 世纪五、 六⼗年代由科学家 Frank Rosenblatt 发明,其受到 Warren McCulloch 和 Walter Pitts 早期著 作的影响。今天,使⽤其它⼈⼯神经元模型更为普遍 —— 在这本书中,以及更多现代的神经⽹ 络著作中,主要使⽤的是⼀种叫做 S 型神经元的神经元模型。我们很快会讲到 S 型神经元。但 是要理解为什么 S 型神经元被定义为那样的⽅式,值得花点时间先来理解下感知机。 感知机是如何⼯作的呢?⼀个感知机接受⼏个⼆进制输⼊,x1 , x2 , . . .,并产⽣⼀个⼆进制输 出: x1 x2 output x3 ⽰例中的感知机有三个输⼊,x1 , x2 , x3 。通常可以有更多或更少输⼊。Rosenblatt 提议⼀个 简单的规则来计算输出。他引⼊权重,w1 , w2 , . . .,表⽰相应输⼊对于输出重要性的实数。神经 ∑ 元的输出,0 或者 1,则由分配权重后的总和 j wj xj 小于或者⼤于⼀些阈值决定。和权重⼀ 样,阈值是⼀个实数,⼀个神经元的参数。⽤更精确的代数形式: 0 ∑ if j wj xj ≤ threshold output = ∑ (1) 1 if j wj xj > threshold 这就是⼀个感知机所要做的所有事情! 2
13 . 1.1. 感知机 这是基本的数学模型。你可以将感知机看作依据权重来作出决定的设备。让我举个例⼦。这 不是⾮常真实的例⼦,但是容易理解,而且很快我们会有根多实际的例⼦。假设这个周末就要 来了,你听说你所在的城市有个奶酪节。你喜欢奶酪,正试着决定是否去参加。你也许会通过给 三个因素设置权重来作出决定: 1. 天⽓好吗? 2. 你的男朋友或者⼥朋友会不会陪你去? 3. 这个节⽇举办的地点是否靠近交通站点?(你没有⻋) 你可以把这三个因素对应地⽤⼆进制变量 x1 , x2 和 x3 来表⽰。例如,如果天⽓好,我们把 x1 = 1,如果不好,x1 = 0。类似地,如果你的男朋友或⼥朋友同去,x2 = 1,否则 x2 = 0。x3 也类似地表⽰交通情况。 现在,假设你是个嗜好奶酪的吃货,以⾄于即使你的男朋友或⼥朋友不感兴趣,也不管路有 多难走都乐意去。但是也许你确实厌恶糟糕的天⽓,而且如果天⽓太糟你也没法出⻔。你可以 使⽤感知机来给这种决策建⽴数学模型。⼀种⽅式是给天⽓权重选择为 w1 = 6 ,其它条件为 w2 = 2 和 w3 = 2。w1 被赋予更⼤的值,表⽰天⽓对你很重要,⽐你的男朋友或⼥朋友陪你,或 者最近的交通站重要的多。最后,假设你将感知机的阈值设为 5。这样,感知机实现了期望的决 策模型,只要天⽓好就输出 1,天⽓不好则为 0。对于你的男朋友或⼥朋友是否想去,或者附近 是否有公共交通站,其输出则没有差别。 随着权重和阈值的变化,你可以得到不同的决策模型。例如,假设我们把阈值改为 3 。那 么感知机会按照天⽓好坏,或者结合交通情况和你男朋友或⼥朋友同⾏的意愿,来得出结果。换 句话说,它变成了另⼀个不同的决策模型。降低阈值则表⽰你更愿意去。 很明显,感知机不是⼈做出决策使⽤的全部模型。但是这个例⼦说明了⼀个感知机如何能权 衡不同的依据来决策。这看上去也可以⼤致解释⼀个感知机⽹络能够做出微妙的决定: input output 在这个⽹络中,第⼀列感知机 —— 我们称其为第⼀层感知机 —— 通过权衡输⼊依据做出三 个⾮常简单的决定。那第⼆层的感知机呢?每⼀个都在权衡第⼀层的决策结果并做出决定。以这 种⽅式,⼀个第⼆层中的感知机可以⽐第⼀层中的做出更复杂和抽象的决策。在第三层中的感 知机甚⾄能进⾏更复杂的决策。以这种⽅式,⼀个多层的感知机⽹络可以从事复杂巧妙的决策。 顺便提⼀下,当我定义感知机时我说的是感知机只有⼀个输出。在上⾯的⽹络中感知机看上 去像是有多个输出。实际上,他们仍然是单输出的。多个感知机输出箭头仅仅便于说明⼀个感 知机的输出被⽤于其它感知机的输⼊。它和把单个输出线条分叉相⽐,显得讨巧些。 ∑ 让我们简化感知机的数学描述。条件 j wj xj 看上去有些冗⻓,我们可以创建两个符号的 ∑ ∑ 变动来简化。第⼀个变动是把 j wj xj 改写成点乘,w · x ≡ j wj xj ,这⾥ w 和 x 对应权重和 3
14 . 1.1. 感知机 输⼊的向量。第⼆个变动是把阈值移到不等式的另⼀边,并⽤感知机的偏置 b ≡ −threshold 代 替。⽤偏置而不是阈值,那么感知机的规则可以重写为: 0 if w · x + b ≤ 0 output = (2) 1 if w · x + b > 0 我们可以把偏置看作⼀种表⽰让感知机输出 1(或者⽤⽣物学的术语,即激活感知机)有多 容易的估算。对于具有⼀个⾮常⼤偏置的感知机来说,输出 1 是很容易的。但是如果偏置是⼀ 个⾮常小的负数,输出 1 则很困难。很明显,引⼊偏置只是我们描述感知机的⼀个很小的变动, 但是我们后⾯会看到它引导更进⼀步的符号简化。因此,在这本书的后续部分,我们不再⽤阈 值,而总是使⽤偏置。 我已经描述过感知机是⼀种权衡依据来做出决策的⽅法。感知机被采⽤的另⼀种⽅式,是计 算基本的逻辑功能,即我们通常认为的运算基础,例如“与”,“或”和“与⾮”。例如,假设我 们有个两个输⼊的感知器,每个权重为 −2,整体的偏置为 3。这是我们的 感知机: x1 −2 3 −2 x2 这样我们得到:输⼊ 00 产⽣输出 1,即 (−2) ∗ 0 + (−2) ∗ 0 + 3 = 3 是正数。这⾥我⽤ ∗ 符 号来显式地表⽰乘法。但是输⼊ 11 产⽣输出 0,即 (−2) ∗ 1 + (−2) ∗ 1 + 3 = −1 是负数。如此 我们的感知机实现了⼀个与⾮⻔! 与⾮⻔的例⼦显⽰了我们可以⽤感知机来计算简单的逻辑功能。实际上,我们完全能⽤感知 器⽹络来计算任何逻辑功能。原因是与⾮⻔是通⽤运算,那样,我们能在多个与⾮⻔之上构建出 任何运算。例如,我们能⽤与⾮⻔构建⼀个电路,它把两个⼆进制数 x1 和 x2 相加。这需要计 算按位求和,x1 ⊕ x2 ,同时当 x1 和 x2 都为 1 时进位设为 1,即进位位正好是按位乘积 x1 x2 : x1 sum: x1 ⊕ x2 x2 carry bit: x1 x2 为了得到相等的感知机⽹络,我们把所有与⾮⻔替换为感知机,其具有两个输⼊、每个权重 设为 −2,整体偏置为 3。结果我们得到这样的⽹络。注意我已经把右下的与⾮⻔移动了⼀点, 只是为了在图上更⽅便画箭头: 4
15 . 1.1. 感知机 x1 sum: x1 ⊕ x2 x2 carry bit: x1 x2 这个感知机⽹络中有⼀个部分值得注意,最左边的感知机的输出被两次作为底部感知机的输 ⼊。当我定义感知机模型时,我没有说过是否允许这种双输出到同⼀个地⽅。实际上这不重要。 如果我们不想允许这种形式,那可以简单把两条线合并为到⼀个权重为 −4 的连接,而不是两 个权重为 −2 的连接。 (如果你还没明⽩,应该停下来证明这是相等的。 )随着这⼀改变,原先的 ⽹络看起来像下⾯描绘的,所有未标记的权重等于 −2,所有偏置等于 3,标记的单个权重为 −4: x1 sum: x1 ⊕ x2 x2 −4 carry bit: x1 x2 ⽬前为⽌我把像 x1 和 x2 这样的输⼊画成感知机⽹络左边浮动的变量。实际上,可以画⼀ 层额外的感知机 —— 输⼊层 —— 来⽅便对输⼊编码: x1 sum: x1 ⊕ x2 x2 −4 carry bit: x1 x2 这种对有⼀个输出但没有输⼊的感知机的标记法, x1 是⼀种标准。它并不实际表⽰⼀个感知机没有输⼊。为了看清它,假设我们确实有⼀个没有输 ∑ ⼊的感知机。那么加权和 j wj xj 会总是为零,并且感知机在 b > 0 时输出 1,当 b ≤ 0 时输 出 0。那样,感知机会简单输出⼀个固定值,而不是期望值(上例中的 x1 ) 。倒不如完全不把输 ⼊感知机看作感知机,而是简单定义为输出期望值的特殊单元,x1 , x2 , . . .。 5
16 . 1.2. S 型神经元 通过这个加法器例⼦,我们演⽰了⼀个感知机⽹络如何⽤于模拟包含很多与⾮⻔的电路。因 为与⾮⻔在计算机运算中的通⽤性,由此可以得出感知机也同样适⽤的结论。 感知机运算的通⽤性既是令⼈⿎舞的,⼜是令⼈失望的。令⼈⿎舞是因为它告诉我们感知机 ⽹络能和其它计算设备⼀样强⼤。但是它也令⼈失望,因为它看上去只不过是⼀种新的与⾮⻔。 这简直不算个⼤新闻! 然而,实际情况⽐这⼀观点认为的更好。其结果是我们可以设计学习算法,能够⾃动调整⼈ ⼯神经元的权重和偏置。这种调整可以⾃动响应外部的刺激,而不需要⼀个程序员的直接⼲预。 这些学习算法是我们能够以⼀种根本区别于传统逻辑⻔的⽅式使⽤⼈⼯神经元。有别于显式地 设计与⾮或其它⻔,我们的神经⽹络能简单地学会解决问题,这些问题有时候直接⽤传统的电 路设计是很难解决的。 1.2 S 型神经元 学习算法听上去⾮常棒。但是我们怎样给⼀个神经⽹络设计这样的算法呢?假设我们有⼀ 个感知机⽹络,想要⽤它来解决⼀些问题。例如,⽹络的输⼊可以是⼀幅⼿写数字的扫描图像。 我们想要⽹络能学习权重和偏置,这样⽹络的输出能正确分类这些数字。为了看清学习是怎样 ⼯作的,假设我们把⽹络中的权重(或者偏置)做些微小的改动。就像我们⻢上会看到的,这⼀ 属性会让学习变得可能。这⾥简要⽰意我们想要的(很明显这个⽹络对于⼿写识别还是太简单 了!): 任何权重(或偏置)中的微小改变 引起⼀个输出的微小改变 w + ∆w output + ∆output 如果对权重(或者偏置)的微小的改动真的能够仅仅引起输出的微小变化,那我们可以利⽤ 这⼀事实来修改权重和偏置,让我们的⽹络能够表现得像我们想要的那样。例如,假设⽹络错 误地把⼀个“9”的图像分类为“8”。我们能够计算出怎么对权重和偏置做些小的改动,这样⽹ 络能够接近于把图像分类为“9”。然后我们要重复这个⼯作,反复改动权重和偏置来产⽣更好 的输出。这时⽹络就在学习。 问题是当我们给实际⽹络加上感知机时,结果并不像我们想象的那样。实际上,⽹络中单 个感知机上⼀个权重或偏置的微小改动有时候会引起那个感知机的输出完全翻转,如 0 变到 1。 那样的翻转可能接下来引起其余⽹络的⾏为以极其复杂的⽅式完全改变。因此,虽然你的“9” 可能被正确分类,⽹络在其它图像上的⾏为很可能以⼀些很难控制的⽅式被完全改变。这使得 逐步修改权重和偏置来让⽹络接近期望⾏为变得困难。也许有其它聪明的⽅式来解决这个问题。 但是⽬前为⽌,我们还没发现有什么办法能让感知机⽹络进⾏学习。 6
17 . 1.2. S 型神经元 我们可以引⼊⼀种称为 S 型神经元的新的⼈⼯神经元来克服这个问题。S 型神经元和感知机 类似,但是经过修改后,权重和偏置的微小改动只引起输出的微小变化。这对于让神经元⽹络 学习起来是很关键的。 好了, 让我来描述下 S 型神经元。我们⽤描绘感知机的相同⽅式来描绘 S 型神经元: x1 x2 output x3 正如⼀个感知机,S 型神经元有多个输⼊,x1 , x2 , . . .。但是这些输⼊可以取 0 和 1 中的任 意值,而不仅仅是 0 或 1。例如,0.638 . . . 是⼀个 S 型神经元的有效输⼊。同样,S 型神经元 对每个输⼊有权重,w1 , w2 , . . .,和⼀个总的偏置,b。但是输出不是 0 或 1。相反,它现在是 σ(w · x + b),这⾥ σ 被称为 S 型函数1 ,定义为: 1 σ(z) ≡ (3) 1 + e−z 把它们放在⼀起来更清楚地说明,⼀个具有输⼊ x1 , x2 , . . .,权重 w1 , w2 , . . .,和偏置 b 的 S 型神经元的输出是: 1 ∑ (4) 1 + exp(− j wj xj − b) 初看上去,S 型神经元和感知机有很⼤的差别。如果你不熟悉 S 型函数的代数形式,它看上 去晦涩难懂⼜令⼈⽣畏。实际上,感知机和 S 型神经元之间有很多相似的地⽅,跨过理解上的 障碍,S 型函数的代数形式具有很多技术细节。 为了理解和感知机模型的相似性,假设 z ≡ w · x + b 是⼀个很⼤的正数。那么 e−z ≈ 0 而 σ(z) ≈ 1。即,当 z = w · x + b 很⼤并且为正,S 型神经元的输出近似为 1,正好和感知机⼀样。 相反地,假设 z = w · x + b 是⼀个很⼤的负数。那么 e−z → ∞,σ(z) ≈ 0。所以当 z = w · x + b 是⼀个很⼤的负数,S 型神经元的⾏为也⾮常近似⼀个感知机。只有在 w · x + b 取中间值时, 和感知机模型有⽐较⼤的偏离。 σ 的代数形式⼜是什么?我们怎样去理解它呢?实际上,σ 的精确形式不重要 —— 重要的是 这个函数绘制的形状。是这样: 1 顺便提⼀下,σ 有时被称为逻辑函数,而这种新的神经元类型被称为逻辑神经元。既然这些术语被很多从事于神 经元⽹络的⼈使⽤,记住它是有⽤的。然而,我们将继续使⽤ S 型这个术语。 7
18 . 1.2. S 型神经元 sigmoid function 1.0 0.8 0.6 0.4 0.2 0.0 −4 −3 −2 −1 0 1 2 3 4 Z 这个形状是阶跃函数平滑后的版本: step function 1.0 0.8 0.6 0.4 0.2 0.0 −4 −3 −2 −1 0 1 2 3 4 Z 如果 σ 实际是个阶跃函数,既然输出会依赖于 w · x + b 是正数还是负数2 ,那么 S 型神经元 会成为⼀个感知机。利⽤实际的 σ 函数,我们得到⼀个,就像上⾯说明的,平滑的感知机。确 实,σ 函数的平滑特性,正是关键因素,而不是其细部形式。σ 的平滑意味着权重和偏置的微小 变化,即 ∆wj 和 ∆b,会从神经元产⽣⼀个微小的输出变化 ∆output。实际上,微积分告诉我 们 ∆output 可以很好地近似表⽰为: ∑ ∂ output ∂ output ∆output ≈ ∆wj + ∆b (5) ∂wj ∂b j 其中求和是在所有权重 wj 上进⾏的,而 ∂ output/∂wj 和 ∂ output/∂b 符号表⽰ output 分 别对于 wj 和 b 的偏导数。如果偏导数这个概念让你不安,不必惊慌。上⾯全部⽤偏导数的表达 式看上去很复杂,实际上它的意思⾮常简单(这可是个好消息) :∆output 是⼀个反映权重和偏 置变化 —— 即 ∆wj 和 ∆b —— 的线性函数。利⽤这个线性特性,我们⽐较容易细微地修改权重 和偏置的值,从而获得我们需要的细微的输出变化。所以,因为S 型神经元具有与感知机类似的 本质⾏为,它们可以帮助我们了解权重和偏置的变化如何影响输出值。 2 实际上,当 w · x + b = 0 ,感知机输出 0,而同时阶跃函数输出 1。所以严格地说,我们需要修改阶跃函数来符 合这点。但是你知道怎么做。 8
19 . 1.3. 神经⽹络的架构 如果对 σ 来说重要的是形状而不是精确的形式,那为什么要在公式 (3) 中给 σ 使⽤特定的 形式呢?事实上,在下⽂我们还将不时地考虑⼀些神经元,它们给其它激活函数 f (·) 输出是 f (w · x + b)。当我们使⽤⼀个不同的激活函数,最⼤的变化是公式 (5) 中⽤于偏导数的特定值 的改变。事实证明当我们后⾯计算这些偏导数,⽤ σ 会简化数学计算,这是因为指数在求导时 有些可爱的属性。⽆论如何,σ 在神经⽹络的⼯作中被普遍使⽤,并且是这本书中我们最常使⽤ 的激活函数。 我们应该如何解释⼀个 S 型神经元的输出呢?很明显,感知机和 S 型神经元之间⼀个很⼤的 不同是 S 型神经元不仅仅输出 0 或 1。它可以输出 0 到 1 之间的任何实数,所以诸如 0.173 . . . 和 0.689 . . . 的值是合理的输出。这是⾮常有⽤的,例如,当我们想要输出来表⽰⼀个神经⽹络 的图像像素输⼊的平均强度。但有时候这会是个⿇烦。假设我们希望⽹络的输出表⽰“输⼊图 像是⼀个 9”或“输⼊图像不是⼀个 9”。很明显,如果输出是 0 或 1 是最简单的,就像⽤感知 机。但是在实践中,我们可以设定⼀个约定来解决这个问题,例如,约定任何⾄少为 0.5 的输出 为表⽰“这是⼀个 9”,而其它小于 0.5 的输出为表⽰“不是⼀个 9”。当我们正在使⽤这样的约 定时,我总会清楚地提出来,这样就不会引起混淆。 练习 • S 型神经元模拟感知机,第⼀部分 假设我们把⼀个感知机⽹络中的所有权重和偏置乘以⼀个正的常数,c > 0。证明⽹络的⾏ 为并没有改变。 • S 型神经元模拟感知机,第⼆部分 假设我们有上题中相同的设置 —— ⼀个感知机⽹络。同样假设所有输⼊被选中。我们不需 要实际的输⼊值,仅仅需要固定这些输⼊。假设对于⽹络中任何特定感知机的输⼊ x,权 重和偏置遵循 w · x + b ̸= 0。现在⽤ S 型神经元替换所有⽹络中的感知机,并且把权重 和偏置乘以⼀个正的常量 c > 0。证明在 c → ∞ 的极限情况下,S 型神经元⽹络的⾏为 和感知机⽹络的完全⼀致。当⼀个感知机的 w · x + b = 0 时⼜为什么会不同? 1.3 神经⽹络的架构 在下⼀节我会介绍⼀个神经⽹络,我们可以⽤它来很好地分类⼿写数字。准备进⼊下⼀节时, 解释⼀些可以让我们命名⽹络中不同部分的术语是很有帮助的。假设我们有这样的⽹络: output 前⾯提过,这个⽹络中最左边的称为输⼊层,其中的神经元称为输⼊神经元。最右边的,即 输出层包含有输出神经元,在本例中,输出层只有⼀个神经元。中间层,既然这层中的神经元既 不是输⼊也不是输出,则被称为隐藏层。 “隐藏”这⼀术语也许听上去有些神秘 —— 我第⼀次听 9
20 . 1.3. 神经⽹络的架构 到这个词,以为它必然有⼀些深层的哲学或数学涵意 —— 但它实际上仅仅意味着“既⾮输⼊也 ⾮输出”。上⾯的⽹络仅有⼀个隐藏层,但有些⽹络有多个隐藏层。例如,下⾯的四层⽹络有两 个隐藏层: hidden layer output layer input layer 有些令⼈困惑的是,由于历史的原因,尽管是由 S 型神经元而不是感知机构成,这种多层⽹ 络有时被称为多层感知机或者 MLP。在这本书中我不会使⽤ MLP 这个术语,因为我认为这会 引起混淆,但这⾥想提醒你它的存在。 设计⽹络的输⼊输出层通常是⽐较直接的。例如,假设我们尝试确定⼀张⼿写数字的图像上 是否写的是“9”。很⾃然地,我们可以将图⽚像素的强度进⾏编码作为输⼊神经元来设计⽹络。 如果图像是⼀个 64 × 64 的灰度图像,那么我们会需要 4096 = 64 × 64 个输⼊神经元,每个强 度取 0 和 1 之间合适的值。输出层只需要包含⼀个神经元,当输出值小于 0.5 时表⽰“输⼊图 像不是⼀个 9”,⼤于 0.5 的值表⽰“输⼊图像是⼀个 9”。 相⽐于神经⽹络中输⼊输出层的直观设计,隐藏层的设计则堪称⼀⻔艺术。特别是,通过⼀ 些简单的经验法则来总结隐藏层的设计流程是不可⾏的。相反,神经⽹络的研究⼈员已经为隐 藏层开发了许多设计最优法则,这有助于⽹络的⾏为能符合⼈们期望的那样。例如,这些法则 可以⽤于帮助权衡隐藏层数量和训练⽹络所需的时间开销。在本书后⾯我们会碰到⼏个这样的 设计最优法则。 ⽬前为⽌,我们讨论的神经⽹络,都是以上⼀层的输出作为下⼀层的输⼊。这种⽹络被称为 前馈神经⽹络。这意味着⽹络中是没有回路的 —— 信息总是向前传播,从不反向回馈。如果确 实有回路,我们最终会有这样的情况:σ 函数的输⼊依赖于输出。这将难于理解,所以我们不允 许这样的环路。 然而,也有⼀些⼈⼯神经⽹络的模型,其中反馈环路是可⾏的。这些模型被称为递归神经⽹ 络。这种模型的设计思想,是具有休眠前会在⼀段有限的时间内保持激活状态的神经元。这种 激活状态可以刺激其它神经元,使其随后被激活并同样保持⼀段有限的时间。这样会导致更多 的神经元被激活,随着时间的推移,我们得到⼀个级联的神经元激活系统。因为⼀个神经元的 输出只在⼀段时间后而不是即刻影响它的输⼊,在这个模型中回路并不会引起问题。 递归神经⽹络⽐前馈⽹络影响⼒小得多,部分原因是递归⽹络的学习算法(⾄少⽬前为⽌) 不够强⼤。但是递归⽹络仍然很有吸引⼒。它们原理上⽐前馈⽹络更接近我们⼤脑的实际⼯作。 并且递归⽹络能解决⼀些重要的问题,这些问题如果仅仅⽤前馈⽹络来解决,则更加困难。然 而为了篇幅,本书将专注于使⽤更⼴泛的前馈⽹络。 10
21 . 1.4. ⼀个简单的分类⼿写数字的⽹络 1.4 ⼀个简单的分类⼿写数字的⽹络 定义神经⽹络后,让我们回到⼿写识别上来。我们可以把识别⼿写数字的问题分成两个⼦问 题。⾸先,我们希望有个⽅式把包含许多数字的图像分成⼀系列单独的图像,每个包含单个数 字。例如,我们想要把图像 分成六个单独的图像, 我们⼈类可以很容易解决这个分割的问题,但是对于计算机程序来说却是个挑战。⼀旦图像 被分割,那么程序需要把每个单独的数字分类。例如,我们想要我们的程序能识别上⾯的第⼀ 个数字 是 5。 我们将专注于编程解决第⼆个问题,分类单独的数字。这样是因为,⼀旦你有分类单独数字 的有效⽅法,分割问题是不难解决的。有很多途径可以解决分割的问题。⼀种⽅法是尝试不同 的分割⽅式,⽤数字分类器对每⼀个切分⽚段打分。如果数字分类器对每⼀个⽚段的置信度都 ⽐较⾼,那么这个分割⽅式就能得到较⾼的分数;如果数字分类器在⼀或多个⽚段中出现问题, 那么这种分割⽅式就会得到较低的分数。这种⽅法的思想是,如果分类器有问题,那么很可能是 由于图像分割出错导致的。这种思想以及它的变化形式能够⽐较好地解决分割问题。因此,与 其关⼼分割问题,我们不如把精⼒集中在设计⼀个神经⽹络来解决更有趣、更困难的问题,即 ⼿写数字的识别。 我们将使⽤⼀个三层神经⽹络来识别单个数字: 11
22 . 1.4. ⼀个简单的分类⼿写数字的⽹络 hidden layer (n = 15 neurons) output layer 0 1 2 3 4 input layer (784 neurons) 5 6 7 8 9 ⽹络的输⼊层包含给输⼊像素的值进⾏编码的神经元。就像下⼀节会讨论的,我们给⽹络的 训练数据会有很多扫描得到的 28 × 28 的⼿写数字的图像组成,所有输⼊层包含有 784 = 28 × 28 个神经元。为了简化,上图中我已经忽略了 784 中⼤部分的输⼊神经元。输⼊像素是灰度级的, 值为 0.0 表⽰⽩⾊,值为 1.0 表⽰⿊⾊,中间数值表⽰逐渐暗淡的灰⾊。 ⽹络的第⼆层是⼀个隐藏层。我们⽤ n 来表⽰神经元的数量,我们将给 n 实验不同的数值。 ⽰例中⽤⼀个小的隐藏层来说明,仅仅包含 n = 15 个神经元。 ⽹络的输出层包含有 10 个神经元。如果第⼀个神经元激活,即输出 ≈ 1,那么表明⽹络认 为数字是⼀个 0。如果第⼆个神经元激活,就表明⽹络认为数字是⼀个 1。依此类推。更确切地 说,我们把输出神经元的输出赋予编号 0 到 9,并计算出那个神经元有最⾼的激活值。⽐如,如 果编号为 6 的神经元激活,那么我们的⽹络会猜到输⼊的数字是 6。其它神经元相同。 你可能会好奇为什么我们⽤ 10 个输出神经元。毕竟我们的任务是能让神经⽹络告诉我们哪 个数字(0, 1, 2, . . . , 9 )能和输⼊图⽚匹配。⼀个看起来更⾃然的⽅式就是使⽤ 4 个输出神经元, 把每⼀个当做⼀个⼆进制值,结果取决于它的输出更靠近 0 还是 1 。四个神经元⾜够编码这个 问题了,因为 24 = 16 ⼤于 10 种可能的输⼊。为什么我们反而要⽤ 10 个神经元呢?这样做难 道效率不低吗?最终的判断是基于经验主义的:我们可以实验两种不同的⽹络设计,结果证明 对于这个特定的问题而⾔,10 个输出神经元的神经⽹络⽐ 4 个的识别效果更好。但是令我们好 奇的是为什么使⽤ 10 个输出神经元的神经⽹络更有效呢。有没有什么启发性的⽅法能提前告诉 我们⽤ 10 个输出编码⽐使⽤ 4 个输出编码更有好呢? 为了理解为什么我们这么做,我们需要从根本原理上理解神经⽹络究竟在做些什么。⾸先考 虑有 10 个神经元的情况。我们⾸先考虑第⼀个输出神经元,它告诉我们⼀个数字是不是 0。它 12
23 . 1.4. ⼀个简单的分类⼿写数字的⽹络 能那么做是因为可以权衡从隐藏层来的信息。隐藏层的神经元在做什么呢?假设隐藏层的第⼀ 个神经元只是⽤于检测如下的图像是否存在: 为了达到这个⽬的,它通过对此图像对应部分的像素赋予较⼤权重,对其它部分赋予较小 的权重。同理,我们可以假设隐藏层的第⼆,第三,第四个神经元是为检测下列图⽚是否存在: 就像你能猜到的,这四幅图像组合在⼀起构成了前⾯显⽰的⼀⾏数字图像中的 0: 如果所有隐藏层的这四个神经元被激活那么我们就可以推断出这个数字是 0。当然,这不是 我们推断出 0 的唯⼀⽅式 —— 我们能通过很多其他合理的⽅式得到 0 (举个例⼦来说,通过上 述图像的转换,或者稍微变形)。但⾄少在这个例⼦中我们可以推断出输⼊的数字是 0。 假设神经⽹络以上述⽅式运⾏,我们可以给出⼀个貌似合理的理由去解释为什么⽤ 10 个输 出而不是 4 个。如果我们有 4 个输出,那么第⼀个输出神经元将会尽⼒去判断数字的最⾼有效 位是什么。把数字的最⾼有效位和数字的形状联系起来并不是⼀个简单的问题。很难想象出有 什么恰当的历史原因,⼀个数字的形状要素会和⼀个数字的最⾼有效位有什么紧密联系。 上⾯我们说的只是⼀个启发性的⽅法。没有什么理由表明这个三层的神经⽹络必须按照我所 描述的⽅式运⾏,即隐藏层是⽤来探测数字的组成形状。可能⼀个聪明的学习算法将会找到⼀ 些合适的权重能让我们仅仅⽤ 4 个输出神经元就⾏。但是这个启发性的⽅法通常很有效,它会 节省你⼤量时间去设计⼀个好的神经⽹络结构。 练习 • 通过在上述的三层神经⽹络加⼀个额外的⼀层就可以实现按位表⽰数字。额外的⼀层把原 来的输出层转化为⼀个⼆进制表⽰,如下图所⽰。为新的输出层寻找⼀些合适的权重和偏 置。假定原先的 3 层神经⽹络在第三层得到正确输出(即原来的输出层)的激活值⾄少是 0.99,得到错误的输出的激活值⾄多是 0.01。 13
24 . 1.5. 使⽤梯度下降算法进⾏学习 old output layer hidden layer new output layer input layer (784 neurons) 1.5 使⽤梯度下降算法进⾏学习 现在我们有了神经⽹络的设计,它怎样可以学习识别数字呢?我们需要的第⼀样东西是⼀个 ⽤来学习的数据集 —— 称为训练数据集。我们将使⽤ MNIST 数据集,其包含有数以万计的连 带着正确分类器的⼿写数字的扫描图像。MNIST 的名字来源于 NIST ——美国国家标准与技术 研究所 —— 收集的两个数据集改进后的⼦集。这是取⾃ MNIST 的⼀些图像: 正如你看到的,这些数字其实是和本章开始提到的⼀样。当然,当测试我们的⽹络时我们将 要求它识别不在训练集中的图像。 MNIST 数据分为两个部分。第⼀部分包含 60,000 幅⽤于训练数据的图像。这些图像扫描⾃ 250 ⼈的⼿写样本,他们中⼀半⼈是美国⼈口普查局的员⼯,⼀半⼈是⾼校学⽣。这些图像是 28 × 28 ⼤小的灰度图像。第⼆部分是 10,000 幅⽤于测试数据的图像,同样是 28 × 28 的灰度图 像。我们将⽤这些测试数据来评估我们的神经⽹络学会识别数字有多好。为了让其有好的测试 表现,测试数据取⾃和原始训练数据不同的另外⼀组 250 ⼈(尽管仍然分别是美国⼈口普查局 和⾼校学⽣)。这有助于确保我们的系统能识别那些没有看到训练数据的⼈写的数字。 我们将⽤符号 x 来表⽰⼀个训练输⼊。为了⽅便,把每个训练输⼊ x 看作⼀个 28 × 28 = 784 维的向量。每个向量中的项⽬代表图像中单个像素的灰度值。我们⽤ y = y(x) 表⽰对应的期 望输出,这⾥ y 是⼀个 10 维的向量。例如,如果有⼀个特定的画成 6 的训练图像,x,那么 y(x) = (0, 0, 0, 0, 0, 0, 1, 0, 0, 0)T 则是⽹络的期望输出。注意这⾥ T 是转置操作,把⼀个⾏向量 转换成⼀个列向量。 我们希望有⼀个算法,能让我们找到权重和偏置,以⾄于⽹络的输出 y(x) 能够拟合所有的 14
25 . 1.5. 使⽤梯度下降算法进⾏学习 训练输⼊ x。为了量化我们如何实现这个⽬标,我们定义⼀个代价函数3 : 1 ∑ C(w, b) ≡ ∥y(x) − a∥2 (6) 2n x 这⾥ w 表⽰所有的⽹络中权重的集合,b 是所有的偏置,n 是训练输⼊数据的个数,a 是表 ⽰当输⼊为 x 时输出的向量,求和则是在总的训练输⼊ x 上进⾏的。当然,输出 a 取决于 x, w 和 b,但是为了保持符号的简洁性,我没有明确地指出这种依赖关系。符号 ∥v∥ 是指向量 v 的模。我们把 C 称为⼆次代价函数;有时也被称为均⽅误差或者 MSE。观察⼆次代价函数的 形式我们可以看到 C(w, b) 是⾮负的,因为求和公式中的每⼀项都是⾮负的。此外,代价函数 C(w, b) 的值相当小,即 C(w, b) ≈ 0,精确地说,是当对于所有的训练输⼊ x,y(x) 接近于输出 a 时。因此如果我们的学习算法能找到合适的权重和偏置,使得 C(w, b) ≈ 0,它就能很好地⼯ 作。相反,当 C(w, b) 很⼤时就不怎么好了,那意味着对于⼤量地输⼊,y(x) 与输出 a 相差很⼤。 因此我们的训练算法的⽬的,是最小化权重和偏置的代价函数 C(w, b)。换句话说,我们想要找 到⼀系列能让代价尽可能小的权重和偏置。我们将采⽤称为梯度下降的算法来达到这个⽬的。 为什么要介绍⼆次代价呢?毕竟我们最初感兴趣的内容不是能正确分类的图像数量吗?为什 么不试着直接最⼤化这个数量,而是去最小化⼀个类似⼆次代价的间接评量呢?这么做是因为 在神经⽹络中,被正确分类的图像数量所关于权重和偏置的函数并不是⼀个平滑的函数。⼤多 数情况下,对权重和偏置做出的微小变动完全不会影响被正确分类的图像的数量。这会导致我 们很难去解决如何改变权重和偏置来取得改进的性能。而⽤⼀个类似⼆次代价的平滑代价函数 则能更好地去解决如何⽤权重和偏置中的微小的改变来取得更好的效果。这就是为什么我们⾸ 先专注于最小化⼆次代价,只有这样,我们之后才能测试分类精度。 即使已经知道我们需要使⽤⼀个平滑的代价函数,你可能仍然想知道为什么我们在⽅程 (6) 中选择⼆次函数。这是临时想出来的吗?是不是我们选择另⼀个不同的代价函数将会得到完全 不同的最小化的权重和偏置呢?这种顾虑是合理的,我们后⾯会再次回到这个代价函数,并做 ⼀些修改。尽管如此,⽅程 (6) 中的⼆次代价函数让我们更好地理解神经⽹络中学习算法的基 础,所以⽬前我们会⼀直使⽤它。 重复⼀下,我们训练神经⽹络的⽬的是找到能最小化⼆次代价函数 C(w, b) 的权重和偏置。 这是⼀个适定问题,但是现在它有很多让我们分散精⼒的结构 —— 对权重 w 和偏置 b 的解释, 晦涩不清的 σ 函数,神经⽹络结构的选择,MNIST 等等。事实证明我们可以忽略结构中⼤部分, 把精⼒集中在最小化⽅⾯来理解它。现在我们打算忘掉所有关于代价函数的具体形式、神经⽹ 络的连接等等。现在让我们想象只要最小化⼀个给定的多元函数。我们打算使⽤⼀种被称为梯 度下降的技术来解决这样的最小化问题。然后我们回到在神经⽹络中要最小化的特定函数上来。 好了,假设我们要最小化某些函数,C(v)。它可以是任意的多元实值函数,v = v1 , v2 , . . .。注 意我们⽤ v 代替了 w 和 b 以强调它可能是任意的函数 —— 我们现在先不局限于神经⽹络的环 境。为了最小化 C(v),想象 C 是⼀个只有两个变量 v1 和 v2 的函数: 3 有时被称为损失或⽬标函数。我们在这本书中使⽤了代价函数这个术语,但是你应该注意其他的术语,因为它经 常被⽤于研究论⽂和其他神经⽹络的讨论中。 15
26 . 1.5. 使⽤梯度下降算法进⾏学习 2 1 C 1 0 −1 0 0 v2 1 −1 v1 我们想要的是找到 C 的全局最小值。当然,对于上图的函数,我们⼀眼就能找到最小值。那 只意味着,也许我展⽰的函数过于简单了!通常函数 C 可能是⼀个复杂的多元函数,看⼀下就 能找到最小值是不可能的。 ⼀种解决这个问题的⽅式是⽤微积分来解析最小值。我们可以计算导数去寻找 C 的极值点。 运⽓好的话,C 是⼀个只有⼀个或少数⼏个变量的函数。但是变量过多的话那就是噩梦。而且 神经⽹络中我们经常需要⼤量的变量——最⼤的神经⽹络有依赖数亿权重和偏置的代价函数,极 其复杂。⽤微积分来计算最小值已经不可⾏了。 (确定我们将可以通过有两个变量的函数 C 来理解神经⽹络后,我已经两次提到: “嘿,如果 函数有远多于两个变量怎么办?”。对此我只能说很抱歉。请相信我把 C 想象成⼀个⼆元函数是 有助于我们的理解的。有时候这种想象的画⾯会遇到障碍,这正是上⾯两个段落在帮助你克服 的。善于思考数学通常也涉及到有效地利⽤多种直觉上的想象画⾯,学会什么时候⽤什么画⾯ 合适。) 好吧,微积分是不能⽤了。幸运的是,有⼀个漂亮的推导法暗⽰有⼀种算法能得到很好的效 果。⾸先把我们的函数想象成⼀个⼭⾕。只要瞄⼀眼上⾯的绘图就不难理解。我们想象有⼀个 小球从⼭⾕的斜坡滚落下来。我们的⽇常经验告诉我们这个球最终会滚到⾕底。也许我们可以 ⽤这⼀想法来找到函数的最小值?我们会为⼀个(假想的)球体随机选择⼀个起始位置,然后 模拟球体滚落到⾕底的运动。我们可以通过计算 C 的导数(或者⼆阶导数)来简单模拟——这 些导数会告诉我们⼭⾕中局部“形状”的⼀切,由此知道我们的球将怎样滚动。 看到这⾥你可能会以为我们会写下球体的⽜顿运动定理,考虑摩擦⼒、重⼒等影响。实际上, 我们不打算真的去实现这个球体滚落的推导 —— 我们是在设计⼀个最小化 C 的算法,而不是 在⽤物理定律做精确的仿真。对球体的⾁眼观察是为了激发我们的想象而不是束缚我们的思维。 因此与其陷进物理学⾥凌乱的细节,不如我们就这样问⾃⼰:如果我们扮演⼀天的上帝,能够 构造⾃⼰的物理定律,能够⽀配球体可以如何滚动,那么我们将会采取什么样的运动学定律来 让球体能够总是滚落到⾕底呢? 为了更精确地描述这个问题,让我们思考⼀下,当我们在 v1 和 v2 ⽅向分别将球体移动⼀个 很小的量,即 ∆v1 和 ∆v2 时,球体将会发⽣什么情况。微积分告诉我们 C 将会有如下变化: ∂C ∂C ∆C ≈ ∆v1 + ∆v2 (7) ∂v1 ∂v2 我们要寻找⼀种选择 ∆v1 和 ∆v2 的⽅法使得 ∆C 为负;即,我们选择它们是为了让球体滚 落。为了弄明⽩如何选择,需要定义 ∆v 为 v 变化的向量,∆v ≡ (∆v1 , ∆v2 )T ,T 是转置符号。 16
27 . 1.5. 使⽤梯度下降算法进⾏学习 ( )T ∂C ∂C 我们也定义 C 的梯度为偏导数的向量, ∂v , 1 ∂v2 。我们⽤ ∇C 来表⽰梯度向量,即: ( )T ∂C ∂C ∇C ≡ , (8) ∂v1 ∂v2 我们⻢上会⽤ ∆v 和梯度 ∇C 来重写 ∆C 的变化。在这之前我想先澄清⼀些令⼈困惑的关 于梯度的事情。当第⼀次碰到 ∇C 这个符号,⼈们有时会想知道怎么去理解 ∇ 符号。∇ 究竟 是什么意思?事实上你可以把 ∇C 仅仅看做⼀个简单的数学记号 —— 上⾯定义的向量 —— 这 样就不必写两个符号了。这样来看,∇ 仅仅是⼀个符号,犹如⻛中摆动的旗帜,告诉你:“嘿, ∇C 是⼀个梯度向量” 。也有很多其它的数学上不同视⻆对于 ∇ 的专业解释(⽐如,作为⼀个微 分操作),但我们不需要这些观点。 有了这些定义,∆C 的表达式 (7) 可以被重写为: ∆C ≈ ∇C · ∆v (9) 这个表达式解释了为什么 ∇C 被称为梯度向量:∇C 把 v 的变化关联为 C 的变化,正如我 们期望的⽤梯度来表⽰。但是这个⽅程真正让我们兴奋的是它让我们看到了如何选取 ∆v 才能 让 ∆C 为负数。假设我们选取: ∆v = −η∇C (10) 这⾥的 η 是个很小的正数 (称为学习速率) 。⽅程 (9) 告诉我们 ∆C ≈ −η∇C·∇C = −η∥∇C∥2 。 由于 ∥∇C∥2 ≥ 0,这保证了 ∆C ≤ 0,即,如果我们按照⽅程 (10) 的规则去改变 v,那么 C 会 ⼀直减小,不会增加。(当然,要在⽅程 (9) 的近似约束下)。这正是我们想要的特性!因此我 们把⽅程 (10) ⽤于定义球体在梯度下降算法下的“运动定律”。也就是说,我们⽤⽅程 (10) 计 算 ∆v,来移动球体的位置 v: v → v ′ = v − η∇C (11) 然后我们⽤它再次更新规则来计算下⼀次移动。如果我们反复持续这样做,我们将持续减小 C 直到 —— 正如我们希望的 —— 获得⼀个全局的最小值。 总结⼀下,梯度下降算法⼯作的⽅式就是重复计算梯度 ∇C,然后沿着相反的⽅向移动,沿 着⼭⾕“滚落”。我们可以想象它像这样: 2 1 C 1 0 −1 0 0 v2 1 −1 v1 注意具有这⼀规则的梯度下降并不是模仿实际的物理运动。在现实中⼀个球体有动量,使得 17
28 . 1.5. 使⽤梯度下降算法进⾏学习 它岔开斜坡滚动,甚⾄(短暂地)往⼭上滚。只有在克服摩擦⼒的影响,球体才能保证滚到⼭⾕。 相⽐之下,我们选择 ∆v 规则只是说: “往下,现在” 。这仍然是⼀个寻找最小值的⾮常好的规则! 为了使梯度下降能够正确地运⾏,我们需要选择⾜够小的学习速率 η 使得⽅程 (9) 能得到很 好的近似。如果不这样,我们会以 ∆C > 0 结束,这显然不好。同时,我们也不想 η 太小,因为 这会使 ∆v 的变化极小,梯度下降算法就会运⾏得⾮常缓慢。在真正的实现中,η 通常是变化 的,以⾄⽅程 (9) 能保持很好的近似度,但算法⼜不会太慢。我们后⾯会看这是如何⼯作的。 我已经解释了具有两个变量的函数 C 的梯度下降。但事实上,即使 C 是⼀个具有更多变量 的函数也能很好地⼯作。我们假设 C 是⼀个有 m 个变量 v1 , . . . , vm 的多元函数。那么对 C 中 ⾃变量的变化 ∆v = (∆v1 , . . . , ∆vm )T ,∆C 将会变为: ∆C ≈ ∇C · ∆v (12) 这⾥的梯度 ∇C 是向量 ( )T ∂C ∂C ∇C ≡ ,..., (13) ∂v1 ∂vm 正如两个变量的情况,我们可以选取 ∆v = −η∇C (14) 而且 ∆C 的(近似)表达式 (12) 保证是负数。这给了我们⼀种⽅式从梯度中去取得最小值, 即使 C 是任意的多元函数,我们也能重复运⽤更新规则 v → v ′ = v − η∇C (15) 你可以把这个更新规则看做定义梯度下降算法。这给我们提供了⼀种⽅式去通过重复改变 v 来找到函数 C 的最小值。这个规则并不总是有效的 —— 有⼏件事能导致错误,让我们⽆法从梯 度下降来求得函数 C 的全局最小值,这个观点我们会在后⾯的章节中去探讨。但在实践中,梯 度下降算法通常⼯作地⾮常好,在神经⽹络中这是⼀种⾮常有效的⽅式去求代价函数的最小值, 进而促进⽹络⾃⾝的学习。 事实上,甚⾄有⼀种观点认为梯度下降法是求最小值的最优策略。假设我们正在努⼒去改变 ∆v 来让 C 尽可能地减小。这相当于最小化 ∆C ≈ ∇C · ∆v。我们⾸先限制步⻓为小的固定值, 即 ∥∆v∥ = ϵ,ϵ > 0。当步⻓固定时,我们要找到使得 C 减小最⼤的下降⽅向。可以证明,使得 ∇C · ∆v 取得最小值的 ∆v 为 ∆v = −η∇C,这⾥ η = ϵ/∥∇C∥ 是由步⻓限制 ∥∆v∥ = ϵ 所决定 的。因此,梯度下降法可以被视为⼀种在 C 下降最快的⽅向上做微小变化的⽅法。 练习 • 证明上⼀段落的推断。提⽰:可以利⽤柯西-施⽡茨不等式。 • 我已经解释了当 C 是⼆元及其多元函数的情况。那如果 C 是⼀个⼀元函数呢?你能给出 梯度下降法在⼀元函数的⼏何解释么? ⼈们已经研究出很多梯度下降的变化形式,包括⼀些更接近真实模拟球体物理运动的变化形 式。这些模拟球体的变化形式有很多优点,但是也有⼀个主要的缺点:它最终必需去计算 C 的 ⼆阶偏导,这代价可是⾮常⼤的。为了理解为什么这种做法代价⾼,假设我们想求所有的⼆阶 18
29 . 1.5. 使⽤梯度下降算法进⾏学习 偏导 ∂ 2 C/∂vj ∂vk 。如果我们有上百万的变量 vj ,那我们必须要计算数万亿(即百万次的平⽅) 级别的⼆阶偏导4 !这会造成很⼤的计算代价。不过也有⼀些避免这类问题的技巧,寻找梯度下 降算法的替代品也是个很活跃的研究领域。但在这本书中我们将主要⽤梯度下降算法(包括变 化形式)使神经⽹络学习。 我们怎么在神经⽹络中⽤梯度下降算法去学习呢?其思想就是利⽤梯度下降算法去寻找能使 得⽅程 (6) 的代价取得最小值的权重 wk 和偏置 bl 。为了清楚这是如何⼯作的,我们将⽤权重 和偏置代替变量 vj 。也就是说,现在“位置”变量有两个分量组成:wk 和 bl ,而梯度向量 ∇C 则有相应的分量 ∂C/∂wk 和 ∂C/∂bl 。⽤这些分量来写梯度下降的更新规则,我们得到: ∂C wk → wk′ = wk − η (16) ∂wk ∂C bl → b′l = bl − η (17) ∂bl 通过重复应⽤这⼀更新规则我们就能“让球体滚下⼭”,并且有望能找到代价函数的最小值。 换句话说,这是⼀个能让神经⽹络学习的规则。 应⽤梯度下降规则有很多挑战。我们将在下⼀章深⼊讨论。但是现在只提及⼀个问题。为了理 ∑ 解问题是什么,我们先回顾(6) 中的⼆次代价。注意这个代价函数有着这样的形式 C = n1 x Cx , ∥y(x)−a∥2 即,它是遍及每个训练样本代价 Cx ≡ 的平均值。在实践中,为了计算梯度 ∇C,我们 2 ∑ 需要为每个训练输⼊ x 单独地计算梯度值 ∇Cx ,然后求平均值,∇C = n1 x ∇Cx 。不幸的是, 当训练输⼊的数量过⼤时会花费很⻓时间,这样会使学习变得相当缓慢。 有种叫做随机梯度下降的算法能够加速学习。其思想就是通过随机选取小量训练输⼊样本来 计算 ∇Cx ,进而估算梯度 ∇C。通过计算少量样本的平均值我们可以快速得到⼀个对于实际梯 度 ∇C 的很好的估算,这有助于加速梯度下降,进而加速学习过程。 更准确地说,随机梯度下降通过随机选取小量的 m 个训练输⼊来⼯作。我们将这些随机的 训练输⼊标记为 X1 , X2 , . . . , Xm ,并把它们称为⼀个小批量数据。假设样本数量 m ⾜够⼤,我 们期望 ∇CXj 的平均值⼤致相等于整个 ∇Cx 的平均值,即, ∑m ∑ j=1 ∇CXj x ∇Cx ≈ = ∇C (18) m n 这⾥的第⼆个求和符号是在整个训练数据上进⾏的。交换两边我们得到 1 ∑ m ∇C ≈ ∇CXj (19) m j=1 证实了我们可以通过仅仅计算随机选取的小批量数据的梯度来估算整体的梯度。 为了将其明确地和神经⽹络的学习联系起来,假设 wk 和 bl 表⽰我们神经⽹络中权重和偏 置。随机梯度下降通过随机地选取并训练输⼊的小批量数据来⼯作, η ∑ ∂CXj wk → wk′ = wk − (20) m ∂wk j η ∑ ∂CXj bl → b′l = bl − (21) m ∂bl j 4 实际上,更接近万亿次的⼀半,因为 ∂ 2 C/∂vj ∂vk = ∂ 2 C/∂vk ∂vj 。同样,你知道怎么做。 19