作者:David Code
机器之心编译
参与:魔王、思、张倩
David Code 有多个身份:他是旅行作家,通达多国措辞,他还是一名「AI 西席」。没有数学和软件背景的 David 用 18 个月的韶光通过在线课程和博客自学 AI,并花费两年韶光撰写了一篇长文。为了使和他一样没有数学根本的人也能入门人工智能,他在这篇文章中利用了大量类比、例子、故事、图示,将主要的知识点或步骤反复强调。这是一篇真正针对初学者的 AI 教程,不但讲观点,还讲观点的底层事理。由于原文过长,机器之心在编译过程中进行了少量删节。想理解更多细节,请查看原文链接:https://colab.research.google.com/drive/1VdwQq8JJsonfT4SV0pfXKZ1vsoNvvxcH#scrollTo=C810qURdm3hZ。
想学 AI 又担心没有数学背景或软件背景?没紧要,这篇博客非常适宜你。
我曾经花费一年半的韶光自学各种在线课程和博客,过程中有太多专家、太多信息,而且他们的很多不雅观点还有冲突。我在学习过程中常常充满自我疑惑。
我不想要很多专家帮我学习,我只想要一个老师。我希望有人能够拉着我的手说:「Dave,这便是你须要学的东西,请按照这个顺序学。现在我将用图画、有趣的故事、现实示例和浅近易懂的措辞教你学习 AI。」
而现在,我便是那个老师。
为什么是我?和网上的专家不同,我没有数学或编程背景,不过我曾就读于耶鲁大学和普林斯顿大学,环游过 100 多个国家,是一名旅行作家,我曾在《周六夜现场》事情,我的作品得过奖。也便是说,我知道如何通过写作来传达繁芜的观点,知道如何讲故事。我热爱传授教化,也长于创造好的老师。在学习深度学习过程中我碰着了四位精良的老师,他们是 Andrew Trask、Grant Sanderson、Kalid Azad 和我的导师 Adam Koenig。
最主要的是,我理解你正在经历的痛楚。你听说过「专家盲区」(expert blindness)吗?专家向新手讲授某个学科时,由于他成为专家的韶光太久,会忘了初学者对教材的感想熏染。因此专家会快速先容一些繁芜的观点,而这些观点须要分解成小块才能方便初学者节制。或者他们不该用类比、图画或示例来帮助初学者节制观点,导致初学者非常受挫。
每一个初学者都想要专家来教他们 AI。而事实上,你须要的不是专家,而是一名老师。
最好的西席便是那个刚刚学过这些知识的人,由于他仍旧记得自己挣扎过的地方以及战胜方法,并且他可以向你传授捷径。而我便是这个人。我不是专家,但我是个好老师,而且富有激情。
本文利用指南
本文的阅读过程和小说不同,只读一次是无法理解和节制所有内容的。我学数学的朋友见告我,他们常常须要读至少 7 遍数学文本才能开始理解。这不是开玩笑……
为方便讲授,我利用了类比、图画、示例和几何表示。但是请放心,本文在数学层面上是准确而严谨的。请做好阅读本文五遍的准备,无法急速领会也不要焦急。
我在学习繁芜材料的时候,常日会设置计时器,每五分钟响一次,不断地提醒自己不要在绝望中沉沦,要微笑、耐心并坚持下去。这真的有效,相信我。
以下是一些宏不雅观要点:
神经网络是深度学习中非常盛行的前沿技能;深度学习是机器学习的分支;机器学习是人工智能的分支。
深度学习包括四个紧张观点。本文的目标是让读者节制这四个深度学习根本观点:
前馈梯度低落全局最小值反向传播
之前对这四个观点一无所知?没紧要,首先我会利用类比和图示只管即便大略地讲授这些知识,然后不断地回到这四个观点,磋商个中的细节。你该当将本文看作一个「螺旋上升」的学习过程,每一次回到这些观点时你都会收成更多见地。
本文共有五个部分:
1. 深度学习概览:示例、类比、图示、玩笑
2. 28 行代码创建神经网络:神经元和突触
3. 前馈:做出有根据的预测,60000 次迭代
4. 从试错中学习:梯度低落和全局最小值
5. 反向传播:链式法则
1. 深度学习概览
1.1 示例
想象你是一家宠物店的老板,奇迹经营得很成功,而这成功很大程度上是由于你善用 AI 技能。你构建了一个深度神经网络,来选择潜在新顾客,并向他们发送广告。一个月前,你上线了一款新猫砂「Litter Rip!」。你试图找到乐意给自己的猫利用这款猫砂的顾客。
而你的秘密武器是数据集。新猫砂上线一个月后,你对宠物店顾客进行了调查并网络了一些数据。调查包括以下问题:
您有猫吗?您喝入口啤酒吗?过去一个月,您是否访问过我们的网站 LitterRip.com?过去一个月,您是否购买过 Litter Rip! 猫砂?
这四个问题的答案即之前顾客的「特色」(feature)。
那么问题来了:什么使得 AI 网络如此强大?
答案是:它利用调查结果进行演习,从而准确地预测未来顾客的购买行为。
首先,你须要将之前顾客的调查数据和他们对前三个问题的回答输入到网络中,进行演习。该网络利用这些数据预测某位顾客是否确实购买了新款猫砂。然后网络再将预测结果与顾客第四个问题的答案进行比拟。第四个问题的答案便是标签,作为事实供网络进行比拟。例如,如果网络预测结果是「是的,我认为这位顾客买过 Litter Rip! 猫砂」,而这位顾客第四个问题的答案确实是「Yes」,那么你就拥有了一个成功的神经网络。
神经网络通过试错进行自我演习:网络先预测,然后比拟预测结果与第四个问题的真正答案,再从缺点中学习,并在多次迭代中不断改进。
神经网络常日在一个数据集上演习,在另一个数据集上实行预测,理解这一点很主要。一旦你的神经网络很善于根据之前顾客的调查数据预测新款猫砂的购买情形,那么你就可以换一个新的数据集,该数据集包含潜在新顾客的名单。
你从兽医那里得到了新的数据集,这些被调查者回答了前三个问题。现在,如果让你用演习好了的网络在潜在新顾客中预测广告投放的最佳工具,你该怎么做呢?
我们来看下一节。
1.2 类比:神经元和突触
下图是我们将要构建的 3 层神经网络,图中利用的是常见的「神经元和突触」格式:
我们先来看这张图,图中是一个三层的前馈神经网络。左侧为输入层:三个圆圈表示神经元(即节点或特色,该网络将利用前三个调查问题作为特色)。现在,你看着这一列圆圈,想象它们分别代表一位顾客的答案。左上的圆圈包含问题 1「你有猫吗?」的答案,左中圆圈包含问题 2「你喝入口啤酒吗?」的答案,左下圆圈表示问题 3「你是否访问过我们的网站 LitterRip.com?」的答案。那么,如果顾客 1 对这三个问题的答案是「Yes/No/Yes」,则左上圆圈包含 1,左中圆圈包含 0,左下圆圈包含 1。
突触(连接这些圆圈和隐蔽层的所有线)是神经网络用来「思考」的部位。右侧的单个圆圈(它依然和四个突触相连)是网络的预测结果,即「基于输入到网络的特色组合,此处展示了这位顾客购买新款猫砂的概率。」
最右侧标注「y」的单个圆圈表示真值,即每个顾客对第四个调查问题「你是否购买过 Litter Rip! 猫砂?」的回答。这个圆圈有两个选择:0 表示没买过,1 表示买过。神经网络将输出一个预测概率,并将其与 y 进行比拟,查看准确率,然后不才一次迭代中吸取教训。神经网络在数秒韶光内可以完成数万次试错。
上图是神经网络的范例图示。实质上,它描述的是前馈,即我们要先容的第一个紧张观点。你可能以为神经元是该过程中最主要的部分,但是这里的类比彷佛存在一些误导性。事实上,本文要先容的四个深度学习紧张观点的共同驱动力是突触。因此,目前这部分最主要的知识点是:突触使得预测发生。下面一节我会把这一观点类比为落进碗里的乒乓球。
在进行下一个类比之前,我想首先详细阐明一下神经网络之以是强大的缘故原由。
1.3 类比:碗与球
重点来了!
人工智能如此强大的缘故原由是:神经网络利用概率对下一次预测进行渐进式的改进。该过程将试错学习提升到一个全新的层次。
我们先来看一下人类是如何预测的:假设你的桌子上有一些之前顾客的调查结果,阁下还有一叠潜在新顾客的调查结果(即兽医供应给你的调查数据)。人类如何利用之前顾客的调查结果预测未来顾客的购买行为呢?你可能会想:「我的模糊逻辑见告我,喝入口啤酒的顾客和买新款猫砂的顾客没有关联。我查看了顾客调查结果,试图探求出一种模式,我认为拥有猫和访问过 LitterRip.com 网站的顾客购买过 Litter Rip! 猫砂。」
在只有三个调查问题、四名被调查顾客时,这是可行的。但是如果有 40 个问题、4000 名顾客呢?人类如何决定哪一个问题作为实行准确预测的核心成分?人类大脑能够容纳的数量是有限的,我们很难量化 40000 名顾客中的某一位购买新款猫砂的概率。这个数字是 67% 还是 68%?谁知道呢!
现在我们来看神经网络如何实行预测:神经网络不会将预测局限于刀切斧砍的「是」或「否」,相反,它会预测出一个 0 和 1 之间的数字——概率。例如,0.67 表示「该顾客有 67% 的可能购买新款猫砂」,0.13 表示「该顾客有 13% 的可能购买新款猫砂,可能性较小。」
这就解释了为什么给出一个 0 到 1 之间的概率数字是明智的:就算打算机的第一次预测结果与实际情形大相径庭也没有关系。真正主要的是,网络会将概率 0.13 与真值进行比拟(假设真值是 1,即该顾客购买了新款猫砂),网络会把稳到它的预测结果偏离真值 0.87,这是一个比较大的偏差,因此网络会进行调度。网络将保持数字清晰展现,同时调度数字,增加一些值降落另一些值,以找到更好的问题组合,从而使下一次预测能够得到更加准确的预测结果。将该步骤重复数万次,直到打算机终极能够自傲地说:「我很高兴地宣告,现在我的预测结果可以媲美真值了,偏差几近于零。现在我可以准确预测了。」
现在,你知道了深度神经网络的强大缘故原由,它利用概率和试错学习方法,渐进式地改进下一次预测的结果。
我可以用一幅大略清晰的图画描述试错学习过程:网络的试错学习就像顺着碗边滚落的乒乓球,终极将落在碗底。
前面我阐明了神经网络如何实行预测:打算偏差,改进下一次的预测结果,直到偏差减少到险些为零。实行预测的神经网络就像顺着碗侧滚落的乒乓球。我们假设碗底便是「乌托邦」——准确的预测结果,那么网络的第一次预测便是该「预测球」(乒乓球)的起始位置;第二次预测时,乒乓球沿着碗侧向底部提高一点间隔;第三次预测时,球又向碗底提高一点……如下图所示,网络的每一次预测便是乒乓球向碗底提高时的新位置。
预测球滚落以及在到达完美位置(碗底)之前的准确率改进过程包括四步:
前馈:想象一下 1960 年的 IBM 打算机,大到填满全体房间,穿孔卡片从一端输入,答案从另一端输出。上文提到的神经网络以前三个调查问题的数据作为输入,得出预测结果;全局最小值:想象一下桌子上有一个黄色的碗(如上图所示)。桌子表面表示险些零偏差的完美预测结果,那么很显然碗底是最靠近完美预测结果的位置,具备最小的偏差。与碗全体表面(即「全局表面」(global surface))比较,碗底最靠近完美,它具备全局最小偏差值。
网络每次进行更好的预测时,粉色的预测球沿着碗侧向底部全局最小偏差值提高。每一次预测后,网络将预测结果与第四个问题的答案进行比拟,这类似于在特定时刻衡量预测球与碗底的间隔。衡量预测结果与真值的间隔叫做「找出偏差」。网络每次预测的目标都是持续地缩短与全局最小值之间的偏差。
反向传播:想象一位杂技演出者,他能向空中抛接 16 个不同大小和重量的保龄球瓶,并使它们同时悬在空中,乃至可以神奇地调度保龄球瓶的大小和重量。网络在实行预测后,会返回到上一次预测的过程中,查看是否可以做一些调度,以便不才一次预测中缩小偏差,推动小球向碗底提高。梯度低落:想象粉色乒乓球沿着碗侧向碗底滚落,碗底即全局最小值(见上图)。网络就像那个球,碗的表面由网络的每一次预测构成。梯度低落便是球沿着碗侧滚落向碗底(即具备全局最小偏差的预测)的过程。
换句话说:
梯度低落是网络在达到准确预测(即全局最小偏差)前的试错过程,就像乒乓球滚落碗底的过程;前馈即实行预测。预测就像给定时刻球勾留在碗表面某个位置的定格图像;全局最小值即预测险些没有偏差的完美位置(碗底)。我们的目标是到达碗底。网络将预测结果与真值进行比拟,来衡量球目前位置与碗底的间隔(偏差);反向传播即返回到上一次预测,找出错误并改动。反向传播衡量球现在位置到其下桌面的间隔(即偏差),并找出推动球向碗底提高的方法。
记住:我们现在只是粗略理解,以是即便有些地方没有节制也不要担心。
在详细阐明这些观点之前,我想把「碗和球」的类比再推进一步。上图展示了神经网络演习过程中的四个紧张步骤,但过于简化。它准确地表示了只有一个调查问题的网络,该网络也仅基于这一个问题做出预测。
但是,我们想做的是结合三个调查问题找出最佳预测。因此,如果网络在试错迭代过程中利用不同问题组合进行试验,碗会是什么样子呢?答案是:一只凹凸不平的碗。
如下图所示:
图源:https://www.youtube.com/watch?v=IHZwWFHWa-w&t=2s&index=3&list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi
上图中赤色的碗有一些突出和凹陷,为什么会这样呢?
首先,我们必须理解赤色碗由什么构成。从图中看它彷佛是塑料做的……不过并不是,想象它由数百万个红点构成,每个红点都是 3D 网格中的一个点。每个点表示一个可能的调查问题组合,以及该组合中哪个问题对付网络实行预测的等级更高。这个凹凸不平的碗让我们看到了所有可能组合的凹凸不平的表面。
记住这幅图:赤色碗是「所有排列组合的表面」,它像山脉一样有高峰、深谷、山岭、河床。网络无法穷尽浩瀚宇宙中每一个可能的排列组合,这会花费太多打算韶光。因此,它从你随机「抛掷预测球」的位置出发,一起向下走向谷底(即全局最小值)。网络不须要管它从哪里开始出发,它只须要在意从随机的起始点到达碗底即可。
在阐明赤色的凹凸不平处之前,我们先来看从红碗右上角开始的白色虚线。这条线的顶端便是网络的第一次预测。还记得上文先容的赤色乒乓球吗?假设乒乓球就在白线顶端处,白色虚线表示网络预测结果从起始点到全局最小值的路径。也便是说乒乓球沿着这条白色虚线走到偏差最小、预测准确率最高的地方。
但是为什么这条白色虚线路径如此波折呢?缘故原由在于,网络的常规试验须要考虑组合哪些问题、每个问题的权重多大,才能得到偏差最小的最佳预测结果。网络的常规目标是尽可能降落偏差,即让乒乓球尽快到达红碗底部。因此网络常日采取虚线上球所在点的坡度,来确定哪个方向具备最陡峭的坡度,能够实现最快的向下路径。由于坡度不断改变,这条路径就很弯曲。我们来看一个大略的例子:
人类第一眼就会判断这两个问题(「你有猫吗?」和「你访问过我们网站吗?」)是做出预测的根本问题。但是哪个问题对预测准确度影响最大呢?第一个问题影响更大,还是二者五五分?
网络想用这两个问题的不同权重组合进行试验,从而找出实现准确预测的最佳组合。上图赤色碗中的每个突出都表示「走在缺点道路上」的问题组合和问题权重,由于每个突出都使网络的「预测球」愈发偏离底部的全局最小值。而碗中的每个凹陷都表示「走在精确道路上」的问题组合,由于它使预测球离碗底更近。
但是,如果网络找出了三个调查问题的完美权重组合,但预测准确率仍旧只有 60% 旁边,该怎么办?不要怕,网络还有另一个技巧:推断问题(inferred question)。
下面我们用一个大略示例讲述这个主要观点:
我们回过分看关于入口啤酒的那个问题。神经网络一直考试测验不同的问题组合。那么举例来说,或许只有富人才有钱买入口喜力啤酒,而我们都知道养猫的人很可能是富人。(本猫奴的内心:不,我不是,我没有……)那么大概当「你喝入口啤酒吗?」和「你有猫吗?」这两个问题在网络打算过程中是组合问题且权重较高时,预测结果会得到改进。
这里的推断问题便是「富人更有可能购买 Litter Rip 猫砂吗?」。不过我们刚才做了一个(屈曲的)推断:喝入口喜力啤酒和养猫的人可能比较富有。
但是,随着粉色预测球在赤色碗中兜兜转转,它到了突出处,而缘故原由在于网络利用了这个推断问题进行试验。也便是说该推断问题对付改进预测准确率并没有帮助。(可能是由于猫砂不是奢侈品而是养猫者的必需品。)在接下来的迭代中,预测球离开突出处,不再利用这个无用的推断问题。但是它也有可能由于有用的推断问题掉进凹陷处,从而帮助它更快地到达碗底。
上文的示例展示了如何测试推断问题能否有效帮助实现更准确的预测结果。人类利用模糊逻辑探索推断问题,而神经网络考试测验穷尽每一种排列组合。如果试验得到了较好的预测结果,它会保留该问题。如果试验得到了更糟的预测结果,网络将抛弃该问题。
总之,赤色碗表面上每一个红点表示网络利用特定问题组合和权重组合进行的一次试验。每一个凹陷表示「这一步走在了精确的道路上」,网络把稳到这一点并将连续保持。每一个突出处表示「这一步走错了方向」,网络也会把稳到并摒弃它。预测球的路径(白色虚线)歪七扭八,是由于预测球在通往碗底的路上不断探求凹陷处、避免突出处。你可以说白色虚线是预测球通往碗底的最高效路径。
现在我们转回来,更详细地理解一下「前馈」、「全局最小值」、「反向传播」和「梯度低落」。
1.3.1 前馈:将穿孔卡片输入到 1960 年的 IBM 打算机
前馈的目标是创建预测。假设每一次预测是预测球向碗底提高过程中的一个新位置。在上图赤色碗中,网络做的第一次预测由白色虚线右上角的点表示,我们假设预测球就在这个点上。前馈是创建第一次预测的过程。白色虚线上的下一个点即是第二次预测,这样预测球移动到下一个点,之后再进行第三次预测。
大部分 AI 课程和博客不会提及,预测球所在的每个位置由赤色碗底部白色网格的两个坐标轴决定。赤色碗并非在空间中漂移,它位于白色网格之上,该网格具备 X 轴和 Y 轴。
还记得上图先容全局最小值时所用的图像吗?黄色碗位于桌面上。同理,赤色碗位于白色网格上。白色网格即「桌面」,「完美、无偏差的预测位置」即赤色碗实际位于的点。把稳,碗与桌面唯一的连接点是碗底,即白色虚线结束的点(全局最小值)。
预测球在赤色碗中的每次停顿,即每次预测点,都由 3 个坐标轴决定:X 轴和 Y 轴表示网格位置,Z 轴表示预测球到网格的间隔。
现在让我们跳出抽象描述。3D 空间中这三个坐标轴在现实生活中表示什么?
回顾一下,赤色碗表面上每一个红点表示网络利用特定问题组合和权重组合进行的一次试验,那么网络如何实行试验呢?它利用 X 轴和 Y 轴在白色网格上定一个位置,表示特定的问题组合。X 轴和 Y 轴一定会问:「嗨,Z 轴你好,这个组合怎么样?」Z 轴将见告我们该组合的效果——Z 轴卖力衡量偏差。
我们之条件到,碗底,即碗与白色网格相连接的位置,是完美的预测。那么碗中每一个红点都表示偏差,离白色网格越远,偏差就越大。
这点非常主要:白色网格表示网络可以考试测验的问题及权重组合。对付白色网格上的每一个点,其上方的红点表示该组合的偏差值。也便是说,赤色碗上的每个红点表示其下方预测的偏差。赤色碗便是「偏差组成的碗」。只有碗底,红点打仗白色网格的地方,二者之间没有间隔,也因此没有偏差。拜会下图:
上图中的锥形黄色箭头表示 Z 轴,用于衡量偏差。它很有用,你可以从中理解偏差值并学习,以便下次得到更加准确的预测结果。
想象一下,粉色的预测球在白色虚线上移动,黄色箭头总是在预测球下方,并随之移动。粉色球表示网络做出的每次预测,黄色箭头衡量预测球到白色网格的间隔,即衡量每次预测的偏差。它的运行事理是什么?
你可能会想到前馈——以前三个调查问题作为输入并用不同办法进行问题组合,再实行预测,预测结果为 0 到 1 之间的数字,即概率。想象预测球所在的点表示在白色虚线上的数字。我们知道第四个问题的答案是「1」,因此真值是该顾客买过新款猫砂。真值即是全局最小值,是我们改进预测结果的目标,也是赤色碗和白色网格的打仗点。因此,网络用 1 减去预测概率。举例来说,如果网络的第一次预测为 0.5,即该顾客有 50% 的可能性购买过这款猫砂,1 减去 50% 所得的数字表示偏差,黄色箭头就用于衡量该偏差。某种程度上可以说,「真值数字 - 预测球数字 = 黄色箭头数字」。在该示例中,即 1 - 0.5 = 0.5。偏差(黄色箭头的长度)为 0.5(偏差常日用绝对值表示,不能为负值)。
没有第四个调查问题的话,你无法演习网络,由于你须要真值来测试预测结果。黄色箭头衡量网络预测与真值的间隔,即偏差,这个例子中真值为 1。我们的第一次预测(0.5)准确率并不高,0.99 的预测才可以说比较准确。
1.3.2 找到全局最小值
我们的目标是演习神经网络找出减少预测偏差的最快办法,也便是说让黄色箭头变短,这意味着我们须要预测球从起始点到碗底的最高效路径。碗底即「乌托邦」,在那里黄色箭头(预测偏差)的长度险些为 0(全局最小值),即我们的预测具备最小偏差,网络达到非常高的准确率。而预测球到达碗底的最高效路径是那条白色虚线。一旦我们利用第一个数据集完成演习,网络就可以准确预测另一拨潜在新客户购买新款猫砂的概率。
现在想象这个场景:预测球从白色虚线顶端开始,此时黄色箭头(即第一次预测的偏差值)即是 0.5。我们如何让球到达碗底呢?也便是说,我们如何调度网络,使预测球(目前 X,Y 坐标为 (3,3))在白色网格上移动到碗底(碗底点的坐标大致为 (3,0))。目前,我们仅能基于顾客 1 的答案实行预测。那么,我们如何基于每个顾客的回答改进之后每一次预测的结果,直到预测偏差险些为 0?也便是预测球到达碗底,网络演习得足够好,可以利用新数据集做出预测。
找到从不那么准确的预测结果 0.5 到终极第 6 万次预测结果 0.9999 的每一步路径,这便是梯度低落过程。
1.3.3 梯度低落和反向传播
梯度低落表示网络的试错学习过程。对付数学 nerd 来说,它可定义为一个总体方案:改变突触权重、在每次迭代时最大程度上降落偏差。
对付普通人来说,这里有一个更好的阐明:将小球沿着最陡峭的坡度滚下,尽快地到达碗底。反向传播是一种打算梯度的方法,梯度实在便是坡度(slope)。反向传播见告你预测球所在位置的坡度。
坡度在这里非常主要。所有专家都会利用术语「梯度低落」,而梯度的意思便是「坡度」。找到预测球在碗表面位置点的坡度,可以指示出球尽快到达碗底该当移动的方向。
但是,为什么是坡度呢?请考虑梯度低落的过程:
首先,打算机实行前馈预测。用真值(全局最小值所在位置,即碗底)减去预测得到偏差(黄色箭头长度),然后利用反向传播打算偏差的坡度。坡度决定了预测球滚动的方向和速率(即网络该当在数字方面做出多大的调度)。
找出坡度是反向传播的主要工具。如果说梯度低落是总体方案,那么反向传播便是达成方案的紧张工具。
2. 28 行代码创建神经网络
现在我们来看代码。我将首先展示本日要学习的全部代码,然后再进行详细的步骤讲解。建议在两个窗口中打开本文,一个窗口显示代码,另一个连续往下阅读。从下文代码注释中可以看到,我将构建神经网络的过程分解成了 13 个步骤。现在准备好不雅观看打算机从它所犯的缺点中学习并终极识别出模式了吗?
不过,首先我们先来理解矩阵和线性代数的观点。
不才文的代码中,你会看到单词「matrix」或「matrices」(矩阵)。它非常主要:矩阵是这辆汽车的引擎。没有矩阵,神经网络哪儿都去不了。
矩阵是多行数字的凑集。你将碰着的第一个矩阵如下所示,它容纳了宠物店顾客调查的数据。
[1,0,1],[0,1,1],[0,0,1],[1,1,1]
将每一行想象为一名顾客,那么以上矩阵中共有 4 位顾客,每一行的方括号中包含三个数字(1 和 0 分别表示「是」和「否」)。在 1.2 节中,我们看到顾客 1 对前三个调查问题的答案是「Yes/No/Yes」,因此该矩阵的第一行为 1, 0 ,1。第一列是四位顾客对第一个问题「你有猫吗?」的回答。
为了更详细地先容矩阵这一观点,请看下图。图中表示的矩阵与上面的矩阵相同,不过它多了一些标签和颜色,用于强调顾客的回答是一行,特色/问题是一列:
上图厘清了一个最初使我非常困惑的点:行与列之间的关系。
在该矩阵中,每一位顾客的数据被表示为一行中的三个数字。在神经网络图示中(神经元和突触格式),输入层是一个包含三个圆形神经元的列。你须要把稳到,每个神经元并不表示一位顾客,即矩阵中的一行数据。相反,每个神经元表示一个特色,即矩阵中的一列数据。因此,一个神经元内包含所有顾客对同一个问题/特色的答案。拿第一个问题「你有猫吗?」举例,我们只选取了四位顾客的数据,因此上图中该问题的回答中只有四个数字(两个 0、两个 1),而如果我们选取了一百万名顾客的数据,则上图中该神经元内会包含一百万个数字,表示这些顾客对该问题的回答。
到这里,我希望大家能够理解我们为什么须要矩阵:由于我们有不止一位顾客。不才面的神经网络示例中,我们描述了四位顾客,以是我们须要四行数字。
该网络包括不止一个问题。每个问题须要一列,因此我们有三列,分别表示对前三个调查问题的回答(第四个问题将涌如今后面的另一个矩阵中)。
因此我们的矩阵很小,4 行 X 3 列(4 by 3)。不过真实神经网络的矩阵可能拥有数百万位顾客和数百个调查问题。做图像识别的神经网络可能具备数十亿个「顾客」行和特色列。
总结一下,我们须要矩阵使所有数据清晰展现,方便我们在其上进行打算,这样矩阵就把数据组织成都雅、整洁的行与列。
下面我们来看代码,代码选取自 Andrew Trask 的博客,不过注释是我写的。
代码
#This is the \"大众3 Layer Network\"大众 near the bottom of: #http://iamtrask.github.io/2015/07/12/basic-python-network/#First, housekeeping: import numpy, a powerful library of math tools.5 import numpy as np#1 Sigmoid Function: changes numbers to probabilities and computes confidence to use in gradient descent8 def nonlin(x,deriv=False):9 if(deriv==True):10 return x(1-x)11 12 return 1/(1+np.exp(-x))#2 The X Matrix: This is the responses to our survey from 4 of our customers, #in language the computer understands. Row 1 is the first customer's set of #Yes/No answers to the first 3 of our survey questions: #\"大众1\"大众 means Yes to, \"大众Have cat who poops?\"大众 The \"大众0\公众 means No to \"大众Drink imported beer?\"大众#The 1 for \"大众Visited the LitterRip.com website?\"大众 means Yes. There are 3 more rows#(i.e., 3 more customers and their responses) below that. #Got it? That's 4 customers and their Yes/No responses #to the first 3 questions (the 4th question is used in the next step below). #These are the set of inputs that we will use to train our network.23 X = np.array([[1,0,1],24 [0,1,1],25 [0,0,1],26 [1,1,1]])#3The y Vector: Our testing set of 4 target values. These are our 4 customers' Yes/No answers #to question four of the survey, \"大众Actually purchased Litter Rip?\"大众 When our neural network#outputs a prediction, we test it against their answer to this question 4, which #is what really happened. When our network's#predictions compare well with these 4 target values, that means the network is #accurate and ready to take on our second dataset, i.e., predicting whether our #hot prospects from the (hot) veterinarian will buy Litter Rip!34 y = np.array([[1],35 [1],36 [0],37 [0]])#4 SEED: This is housekeeping. One has to seed the random numbers we will generate#in the synapses during the training process, to make debugging easier.40 np.random.seed(1)#5 SYNAPSES: aka \"大众Weights.\"大众 These 2 matrices are the \公众brain\"大众 which predicts, learns#from trial-and-error, then improves in the next iteration. If you remember the #diagram of the curvy red bowl above, syn0 and syn1 are the #X and Y axes on the white grid under the red bowl, so each time we tweak these #values, we march the grid coordinates of Point A (think, \"大众moving the yellow arrow\"大众)#towards the red bowl's bottom, where error is near zero.47 syn0 = 2np.random.random((3,4)) - 1 # Synapse 0 has 12 weights, and connects l0 to l1.48 syn1 = 2np.random.random((4,1)) - 1 # Synapse 1 has 4 weights, and connects l1 to l2.#6 FOR LOOP: this iterator takes our network through 60,000 predictions, #tests, and improvements.52 for j in range(60000): #7 FEED FORWARD: Think of l0, l1 and l2 as 3 matrix layers of \"大众neurons\"大众 #that combine with the \"大众synapses\"大众 matrices in #5 to predict, compare and improve. # l0, or X, is the 3 features/questions of our survey, recorded for 4 customers.57 l0=X58 l1=nonlin(np.dot(l0,syn0))59 l2=nonlin(np.dot(l1,syn1)) #8 The TARGET values against which we test our prediction, l2, to see how much #we missed it by. y is a 4x1 vector containing our 4 customer responses to question #four, \"大众Did you buy Litter Rip?\公众 When we subtract the l2 vector (our first 4 predictions) #from y (the Actual Truth about who bought), we get l2_error, which is how much #our predictions missed the target by, on this particular iteration.66 l2_error = y - l2 #9 PRINT ERROR--a parlor trick: in 60,000 iterations, j divided by 10,000 leaves #a remainder of 0 only 6 times. We're going to check our data every 10,000 iterations #to see if the l2_error (the yellow arrow of height under the white ball, Point A) #is reducing, and whether we're missing our target y by less with each prediction.72 if (j% 10000)==0:73 print(\"大众Avg l2_error after 10,000 more iterations: \"大众+str(np.mean(np.abs(l2_error))))#10 This is the beginning of back propagation. All following steps share the goal of # adjusting the weights in syn0 and syn1 to improve our prediction. To make our # adjustments as efficient as possible, we want to address the biggest errors in our weights. # To do this, we first calculate confidence levels of each l2 prediction by # taking the slope of each l2 guess, and then multiplying it by the l2_error. # In other words, we compute l2_delta by multiplying each error by the slope # of the sigmoid at that value. Why? Well, the values of l2_error that correspond # to high-confidence predictions (i.e., close to 0 or 1) should be multiplied by a # small number (which represents low slope and high confidence) so they change little. # This ensures that the network prioritizes changing our worst predictions first, # (i.e., low-confidence predictions close to 0.5, therefore having steep slope). 88 l2_delta = l2_errornonlin(l2,deriv=True) #11 BACK PROPAGATION, continued: In Step 7, we fed forward our input, l0, through #l1 into l2, our prediction. Now we work backwards to find what errors l1 had when #we fed through it. l1_error is the difference between the most recent computed l1 #and the ideal l1 that would provide the ideal l2 we want. To find l1_error, we #have to multiply l2_delta (i.e., what we want our l2 to be in the next iteration) #by our last iteration of what we thought were the optimal weights (syn1). # In other words, to update syn0, we need to account for the effects of # syn1 (at current values) on the network's prediction. We do this by taking the # product of the newly computed l2_delta and the current values of syn1 to give # l1_error, which corresponds to the amount our update to syn0 should change l1 next time.100 l1_error = l2_delta.dot(syn1.T) #12 Similar to #10 above, we want to tweak this #middle layer, l1, so it sends a better prediction to l2, so l2 will better #predict target y. In other words, tweak the weights in order to produce large #changes in low confidence values and small changes in high confidence values. #To do this, just like in #10 we multiply l1_error by the slope of the #sigmoid at the value of l1 to ensure that the network applies larger changes #to synapse weights that affect low-confidence (e.g., close to 0.5) predictions for l1.109 l1_delta = l1_error nonlin(l1,deriv=True) #13 UPDATE SYNAPSES: aka Gradient Descent. This step is where the synapses, the true #\"大众brain\"大众 of our network, learn from their mistakes, remember, and improve--learning! # We multiply each delta by their corresponding layers to update each weight in both of our #synapses so that our next prediction will be even better.115 syn1 += l1.T.dot(l2_delta)116 syn0 += l0.T.dot(l1_delta)#Print results!119 print(\"大众Our y-l2 error value after all 60,000 iterations of training: \"大众)120 print(l2)
2.1 Sigmoid 函数:行 8-12
sigmoid 函数在网络学习过程中起到非常主要的浸染。
「nonlin()」是一种 sigmoid 函数类型,叫做 logistic 函数。logistic 函数在科学、统计学和概率论中非常常见。此处该函数的表达有些繁芜,由于这里它作为两个函数利用:
第一个函数是将矩阵(此处表示为 x)放入括号内,将每个值转换为 0 到 1 之间的数字(即统计概率)。转换过程通过代码行 12 实现:return 1/(1+np.exp(-x))。
那么为什么须要统计概率呢?神经网络不会预测 0 或 1,它不会直接吼「哇,顾客 1 绝对会买这款猫砂!
」,而是预测概率:「顾客 1 有 74% 的可能购买这款猫砂」。
这里的差异很大,如果你直接预测 0 和 1,那么网络就没有改进空间了。要么对要么错。但是利用概率的话就有改进空间。你可以调度系统,每一次使概率增加或减少几个点,从而提升网络的准确率。这是一个受控的增量过程,而不是盲猜。
将数字转换成 0 到 1 之间的数字这一过程非常主要,它带给我们四大上风。下文将详细谈论这些上风,现在我们先来看 sigmoid 函数如何将其括号内每个矩阵的每个数字转换成 0 到 1 之间的数字,并使其落不才图的 S 曲线上:
图源:https://iamtrask.github.io/2015/07/12/basic-python-network/
sigmoid 的第一个函数将矩阵中的每个值转换为统计概率,而它的第二个函数如代码行 9 和 10 所示:
' if(deriv==True):return x(1-x)'
该函数将给定矩阵中的每个值转换成 sigmoid 函数 S 曲线上特定点处的坡度。该坡度值也叫做置信度(confidence measure)。也便是说,该数值回答了这个问题:我们对该数值能够准确预测结果的自傲程度如何?你可能会想:这又能怎么样呢?我们的目标是神经网络可靠地做出准这是我们的标签确的预测。而实现这一目标的最快办法便是修复置信度低、准确率低的预测,不改变置信度高、准确率高的预测。「置信度」这一观点非常主要,下文我们将深入解读它。
接下来我们看第 2 步:
2.2 创建输入 X:行 23-26
代码行 23-26 创建了一个输入值的 4x3 矩阵,可用于演习网络。X 将成为网络的 layer 0(或 l0),现在开始创建神经网络吧!
以下是我们从顾客调查中得到的特色集,只不过用打算性能理解的措辞表达出来:
Line 23 creates the X input (which becomes l0, layer 0, in line 57)X: [1,0,1],[0,1,1],[0,0,1],[1,1,1]
我们有四个顾客,他们分别回答了三个问题。前面我们谈论过第一行 1,0,1 是顾客 1 的答案。将这个矩阵的每一行看作即将输入网络的演习样本,每一列便是输入的一个特色。因此矩阵 X 可被描述为下图,该矩阵即为图中的 l0:
你可能会想:矩阵 X 是怎么变成图中的 layer 0 的?稍后我会阐明这一点。
接下来,我们将创建精确答案列表。
2.3 创建输出 y:行 34-37
这是我们的标签,即第四个调查问题「你是否购买过新款猫砂?」的答案。看下面这列数字,顾客 1 回答的是「Yes」,顾客 2 回答的是「Yes」,顾客 3 和 4 回答的是「No」。
如果把 y 看作「目标」值的话,我将画一个箭靶。随着网络的改进,它射出的箭离靶心越来越近。一旦网络可以根据矩阵 X 供应的输入准确预测 4 个目标值,则网络准备就绪,可以在其他数据集上实行预测了。
2.4 天生随机数:行 40
这一步是「做家务」。我们必须天生随机数(随机数将在演习过程的下一步天生突触/权重),以使 debug 过程更加大略。你不必理解这行代码的事情事理,只须要利用它就好了。
天生随机数的缘故原由是,你必须从某个地方开始。因此我们从一组捏造数字开始,然后在 6 万次迭代中逐步改变每一个数字,直到它们输出具备最小偏差值的预测。这一步使得测试可重复(即利用同样的输入测试多次,结果仍旧相同)。
2.5 创建突触(即权重):行 47-48
第一次看到下图时,你可能会认为神经网络的「大脑」是那些圆圈(神经元)。而事实上,神经大脑的真正核心是那些能够学习和改进的部分——突触,也便是图中那些连接圆圈的线。这两个矩阵——syn0 和 syn1 才是网络的真正大脑。它们是网络用来试错学习、实行预测、比拟目标值和预测,进而改进下一次预测结果的部分。
把稳代码 syn0 = 2np.random.random((3,4)) - 1 创建了 3x4 矩阵,并为它天生随机数。这将是突触(或权重)的第一层 Synapse 0,它连接 l0 和 l1。该矩阵如下所示:
我曾经在这里犯了一个错:我无法理解为什么 syn0 该当是 3x4 矩阵。我认为它该当是 4x3 矩阵,由于 syn0 必须与 l0 相乘,而后者是 4x3 矩阵,我们为什么不让两个矩阵的数字按行与列排列整洁呢?
而这便是我的缺点:4x3 乘 4x3 能够使数字排列整洁?这是错的。事实上,如果我们想要数字排列整洁,我们就该当让 4x3 乘 3x4。这是矩阵乘法里的一项根本且主要的规则。仔细查看下图中的第一个神经元,该神经元内是每位顾客对「你有猫吗?」这个问题的回答。以下是 4x3 layer0 矩阵的第一列:
[1][0][0][1]
现在把稳,有四条线(突触)将 l0 中「你有猫吗?」这个神经元与 l1 的四个神经元连接起来。这意味着上述列 1,0,0,1 中的每个数字都要与四个不同权重相乘,因此得到 16 个值。l1 确实是一个 4x4 矩阵。
把稳,现在我们要对第二个神经元内的四个数字实行同样的操作,也得到 16 个值。我们将这 16 个值中的每个值与刚才创建的值中的对应值相加。
重复这个步骤,直到将第三个神经元中的四个数字也处理完毕。这样 4x4 l1 矩阵就有 16 个值,每个值是三次乘法所得值的对应相加结果。
也便是说,3 个调查问题 x 4 位顾客 = 3 个神经元 x 4 个突触 = 3 个特色 x 4 个权重 = 3x4 矩阵。
看起来很繁芜?习气就好了。而且打算机会替你实行乘法操作。我只是想帮助大家理解其下的底层操作。当你看到下图时,这些线不会说谎。
大概你会迷惑,代码行 47 中的「2」和「-1」是哪儿来的。np.random.random 函数天生均匀分布于 0 到 1 之间的随机数(对应的均匀值为 0.5),而我们想让随机数初始值的均匀值为 0。这样该矩阵中的初始权重不会存在倾向于 1 或 0 的先验偏置(在最开始的时候,网络不知道接下来会发生什么,因此它对其预测结果是没有信心的,直到我们在每个迭代后更新它)。
那么,我们如何将一组均匀值为 0.5 的数字转变为均匀值为 0 的数字呢?首先,将所有随机数乘 2(这样所有数字分布在 0 到 2 之间,均匀值为 1),然后减去 1(这样所有数字分布在-1 到 1 之间,均匀值为 0)。这便是「2」和「-1」涌现的缘故原由。
接下来看下一行代码:syn1 = 2np.random.random((4,1)) - 1 创建了一个 4x1 向量,并为它天生随机数。这便是网络第二层的权重 Synapse 1,它连接 l1 和 l2。
for loop 使网络实行 6 万次迭代。每次迭代中,网络利用顾客调查数据 X 作为输入,基于该数据得出对顾客购买新款猫砂概率的最佳预测。然后将预测与真值进行比拟,再从缺点中学习,不才次迭代中做出更好的预测。该过程持续 6 万次,直到网络通过试错学会如何准确预测。然后这个网络可以利用任意输入数据,并准确预测可能购买新款猫砂的顾客。
2.6 For Loop:行 52
for loop 使网络实行 6 万次迭代。每次迭代中,网络利用顾客调查数据 X 作为输入,基于该数据得出对顾客购买新款猫砂概率的最佳预测。然后将预测与真值进行比拟,再从缺点中学习,不才次迭代中做出更好的预测。该过程持续 6 万次,直到网络通过试错学会如何准确预测。然后这个网络可以利用任意输入数据,并准确预测可能购买新款猫砂的顾客。
3. 前馈:做出有根据的预测,60000 次迭代
网络在这一步骤开始实行预测。这是深度学习过程中最令人愉快的部分,以是我打算从三个不同角度先容这个观点:
关于前馈的迷人童话关于前馈的俏丽画作为什么矩阵乘法是前馈的引擎
3.1 城堡和生命的意义:前馈网络
想象你自己是一个神经网络。恰好你是一个有驾照的神经网络,而且喜好开快车和神秘的心灵之旅。你急迫想找到生命的意义。奇妙的是,你刚好创造只要驱车前往某个城堡,神秘先知将见告你生命的意义。天啊!
不用说,你肯定特殊想找到先知的城堡。先知就代表真值,也便是神秘问题「你买过新款猫砂吗?」的答案。也便是说,如果你的预测与真值匹配,那么你就到达先知城堡,即 l2 偏差为 0、黄色箭头的长度为 0、粉色乒乓球到达碗底。
不过,找到先知城堡须要一些耐心和坚持,你须要考试测验数千次,迷路数千次。(小提示:数千次旅程 = 迭代,不断迷路 = l2 预测存在偏差,偏差使得你离先知城堡 y 还有间隔。)
但是也有好:你知道随着韶光的流逝,每一次旅程并不是没故意义,你会越来越靠近先知(先知城堡 y 正在闪耀……)。而坏是每一次当你无法到达城堡时,第二天醒来你又回到了原点(即 Layer 0,输入特色,3 个调查问题),必须从那里重新出发(新的迭代)。这个过程有点像下图:
幸运的是,这个故事有一个完美的结局,你一直考试测验、不断修正途径,在进行了 58000 次试验后终于到达了目标。这很值得。
我们来看一下从你的屋子 X 到先知城堡 y 的个中一次旅程(迭代):每一次旅程都是代码行 57-59 所实行的前馈,每天你都到达一个新地方,但是它们都不是你的目的地。你当然想知道如何不才一次旅程中更靠近城堡,我会在这个故事的后续篇中阐明。
接下来,我们来看一个更大略的示例。
3.2 关于前馈的俏丽画作
接下来我们来看 16 个权重中的个中一个。这个权重是 syn0,12 条线中最上方那条,连接 l0 和 l1 最上方的神经元。出于简洁性考虑,我们称其为 syn0,1(syn0(1,1) 的简化,表示矩阵 syn0 的行 1 列 1)。如下图所示:
为什么表示 l2 和 l1 神经元的圆圈被从中间分割开了?圆圈的左半边(带有 LH 字样)是 sigmoid 函数的输入值,右半边是 sigmoid 函数的输出:l1 或 l2。在这个语境下,sigmoid 函数只是将前一层与前一个突触相乘,并转换为 0 到 1 之间的值。代码如下:
return 1/(1+np.exp(-x))
这里的前馈利用了我们的一个演习样本,l0 的第 1 行,即「顾客 1 对 3 个调查问题的回答」:[1,0,1]。因此,我们首先将 l0 的第一个值与 syn0 的第一个值相乘。假设 syn0 矩阵已经由多次演习迭代(我们在 2.4 节已经进行过初始化了),现在该矩阵如下所示:
syn0: [ 3.66 -2.88 3.26 -1.53][-4.84 3.54 2.52 -2.55] [ 0.16 -0.66 -2.82 1.87]
到这里,或许你会迷惑:为什么 syn0 的值与 2.4 节创建的 syn0 如此不同?好问题。前面先容的很多矩阵有逼真的初始值,就彷佛它们刚被打算机通过随机种子创建出来一样。而这里和下面的矩阵并非初始值。它们是经由多次演习迭代的,因此它们的值已经在学习过程中经由了更新和改变。
现在,我们用 l0 的第一个值 1 与 syn0 的第一个值 3.66 相乘,看看会得到什么:
下面是前馈的伪代码,你可以借助上图(从左至右的顺序)帮助理解。
下面,我们再从另一个角度看前馈过程的底层数学事理。
3.3 前馈的数学事理
l0 x syn0 = l1LH,在这个示例中即 1 x 3.66 = 3.66,不要忘却还要加上其余两个 l0 值和 syn0 对应权重的乘积。在该示例中,l0,2 x syn0,2= 0 x something = 0,l0,3 x syn0,3 中 l0,3=1,从上一节中我们知道 syn0,3 = 0.16,因此 l0,3 x syn0,3 = 1 x 0.16 = 0.16。因此 l0,1 x syn0,1 + l0,3 x syn0,3 = 3.66 + 0.16 = 3.82,即 l1_LH = 3.82。
接下来,我们将 l1_LH 输入 nonlin() 函数,将该数字转换为 0 到 1 之间的概率。Nonlin(l1_LH) 利用代码 return 1/(1+np.exp(-x)),因此该示例中,1/(1+(2.718^-3.82))=0.98,l1 = 0.98。
那么,在公式 1/(1+np.exp(-x)) = [1/(1+2.718^-3.82))] = 0.98 中发生了什么呢?打算机利用代码 return 1/(1+np.exp(-x)) 代替了我们的人工打算,我们可以通过下图看到在 sigmoid 曲线上 x = 3.82 所对应的 y 值:
图源:https://iamtrask.github.io/2015/07/12/basic-python-network/
把稳,X 轴上 3.82 在蓝色曲线上对应点的对应 y 值是 0.98,而代码将 3.82 转换为 0 到 1 之间的概率。上图有助于大家理解该打算并不神秘,也不抽象,打算机只不过做了和我们一样的事:它利用数学查看上图中 X 轴上 3.82 对应的 y 值,仅此而已。
同理,我们重复以上步骤,打算出 l2_LH 和 l2 的值。至此,我们就完成了第一次前馈。
现在,为了简洁起见,我们把所有变量放在一起,如下所示:
l0=1syn0,1=3.66l1_LH=3.82l1=0.98syn1,1=12.21l2_LH=0l2=~0.5y=1 (this is a \"大众Yes\"大众 answer to survey Question 4, \公众Actually bought Litter Rip?\"大众)l2_error = y-l2 = 1-0.5 = 0.5
现在,我们来看让这统统实现的矩阵乘法(对矩阵乘法和线性代数陌生的朋友,可以先学习 Grant Sanderson 的课程:https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)。
首先,在代码行 58,我们将 4x3 l0 和 3x4 Syn0 相乘,创建(隐蔽层)l1,它是一个 4x4 矩阵:
在第 58 行代码中,我们将 l1 输入 nonlin() 函数,得到一个 0 到 1 之间的概率值:
1/(1 + 2.781281^-x)This creates layer 1, the hidden layer of our neural network:l1: [0.98 0.03 0.61 0.58][0.01 0.95 0.43 0.34][0.54 0.34 0.06 0.87][0.27 0.50 0.95 0.10]
看不懂也没紧要,我们来看一个大略的演习示例。第一行(顾客 1 的调查数据)[1,0,1] 是一个 1x3 矩阵。我们将其乘以 syn0(3x4 矩阵),得到的 l1 是 1x4 矩阵。过程如下所示:
把稳,在代码第 58 行 l1=nonlin(np.dot(l0,syn0)),我们将 l1 输入 sigmoid 函数,由于我们须要一个 0 到 1 的数值。
从这行代码中,我们可以看到 sigmoid 函数的第一大上风。当我们将 l0 和 syn0 的点乘矩阵输入到 nonlin() 函数时,sigmoid 函数将矩阵中的每个值转换成 0 到 1 之间的概率。
3.4 核心重点:隐蔽层中的推断问题
我们为什么要关心统计概率呢?我认为缘故原由在于,统计概率是让一堆沉默矩阵焕发生机并像小孩一样学习的紧张成分!
在第一层中,当我们将 l0 乘以 syn0 时,为什么要考试测验给 syn0 的权重赋不同的值呢?由于我们想考试测验不同的特色问题组合,创造对预测结果帮助最大的问题组合。上文举过一些拙劣的例子,推断出有猫且喝入口啤酒的人更有可能购买新款猫砂,从而利用权重强化这两个特色组合。
另一个例子:如果一些顾客没有养猫,但他们喝入口啤酒且访问过 Litter Rip.com (http://rip.com/) 网站,我们可以推断出这些顾客热衷技能:他们喝入口啤酒由于他们欣赏其供应链物流,他们访问网站,各种各样的网站,解释他们很显然热衷技能。因此我们可以推断出,这些顾客可能会出于对这款猫砂前辈技能的欣赏而购买它,只管他们可能实际上并没有养猫。以是我们或许须要调度 syn0 的权重,强化这些特色之间的连接。
现在你明白了吗?当我们将调查问题的回答 l0 与 syn0 中的权重(每个权重表示我们对一个推断问题对预测结果的主要程度的最佳预测)相乘时,我们是在考试测验不同的答案组合,以查看哪些组合对预测结果最有帮助。很明显,在 6 万次迭代中,访问过猫砂网站的猫主人更有可能购买这款猫砂,因此在迭代的过程中它们对应的权重会增加,即其统计概率更靠近 1 而不是 0。而喝入口啤酒却没有猫的人购买这款猫砂的可能性较低,因此对应的权重较小,即其统计概率更靠近 0 而不是 1。是不是很奇妙?这就像数字谱写的诗歌,这些是会推理和思考的矩阵!
这也是我为什么大费周章先容这个的缘故原由。你是否经历过,一些傲慢的软件工程师或制造惶恐的见告你,神经网络隐蔽层是潘多拉的魔盒?而事实上它的底层并没有什么「神奇邪术」。这些数学知识清晰、优雅而俏丽。你可以节制它,只要有耐心肯坚持。
接下来我们连续看矩阵乘法。
3.5 用神经元和突触的形式可视化矩阵乘法
我们用神经元和突触的形式可视化 l0 和 syn0,如下图所示:
上图展示了输入 l0 的行 1 如何完成在网络中的第一步。第一行代表顾客 1 对三个调查问题的答案。这三个数字须要乘以 syn0 的 12 个值,然后网络还要对其他三位顾客的答案进行同样的处理,那么如何清晰地展现这些数字并进行打算呢?
这里的关键在于,将四位顾客看作一个「batch」(批次),他们在个中堆叠在一起,即一共 4 个 stack。那么,最上面的那个 stack 便是第一行(顾客 1),依此类推。如上图所示,你将第一行的三个数字和 syn0 的 12 个值相乘,再相加,末了得到 l1 最上面 stack 的四个值。
接着是 batch 中的第二个 stack——顾客 2 的回答是 0,1,1。将这三个数字和 syn0 的 12 个值相乘,再相加,末了得到 l1 第二个 stack 的四个值。
依此类推。其核心在于一次打算一个 stack,这样不管 batch 中有多少个 stack,四个还是四百万个,你都可以很好地处理。你可能会说每个特色都有一个 batch,在猫砂这个示例中,每个调查问题(特色)的 batch 为 4,由于只有四位顾客的答案。但它也可能是四百万。「full batch configuration」的观点是非常常见的模型,接下来我将阐明这一点。
实在认为给定特色具备一个 batch 的值是最随意马虎理解的。当你看到一个特色时,你知道它底下有一个 batch 的值。
就像代码行 59 所示,我们把 4x4 l1 和 4x1 syn1 相乘,然后输入 sigmoid 函数得出 4x1 l2,其每个值都是 0 到 1 的统计概率。
l1 (4x4): [0.98 0.03 0.61 0.58] [ 12.21][0.01 0.95 0.43 0.34] X [ 10.24] =[0.54 0.34 0.06 0.87] [ -6.31][0.27 0.50 0.95 0.10] [-14.52]Then pass the above 4x1 product through \"大众nonlin()\"大众 and you get l2, our prediction:l2: [ 0.50] [ 0.90] [ 0.05] [ 0.70]
那么这四个预测结果见告我们什么呢?预测值间隔 1 越近,则该顾客购买这款猫砂的可能性越高;预测值间隔 0 越近,则该顾客购买这款猫砂的可能性越低。
现在我们完成了前馈部分。接下来我们将看 6 万次迭代过程中如何调度网络权重,使预测结果越来越好。
4. 从试错中学习:梯度低落
4.1 梯度低落概览
梯度低落的目的是什么?是为了更好地调度网络权重,从而不才次迭代中得到更好的预测结果。也便是说,网络的突触矩阵中的某些值要被增减。为了调度这些值,我们必须回答以下两个主要问题:
我该当按什么方向调度数字?该当增加还是减少数值?正方向还是负方向?……
数值该当增减多少?
下面我们将详细阐明这两个根本问题。还记得上文的赤色碗吗?「梯度」便是「坡度」,「梯度低落」即打算出使小球从碗表面上的某个点尽快低落到碗底的最优坡度。
梯度低落的第一步即,打算当前的预测结果与真值 y(1/yes 或 0/no)之间的差距。
4.2 预测结果与调查问题 4 的答案比较有多大差距?
代码行 66:
l2_error = y - l2
第一次预测结果间隔目标值「Yes/1」(顾客 1 对第四个调查问题的回答真值是「购买过」)有多远间隔呢?我们须要将 l2 预测值与 y 值(1)进行比拟,即 y 值减去 l2 得到的便是 l2_error——「预测值间隔目标值 y 的间隔」。
因此,我们可以想象这幅图景:网络利用每位顾客的回答作为输入,并操作这些数据,以得到顾客是否购买猫砂的预测结果。
我们有四位顾客,网络就做了四次预测。因此 l2_error 是四次偏差的向量(每个偏差针对一次预测)。接下来我们将打印出该偏差:
打印偏差:行 72-73
72 if (j% 10000)==0:73 print(\"大众Avg l2_error after 10,000 more iterations: \公众+str(np.mean(np.abs(l2_error))))
行 72 使打算机每隔一万次迭代打印一次 l2_error。这有助于我们每隔一万次查看网络的学习效果和进展。if (j% 10000)==0: 表示「如果你的迭代器所处的迭代次数除以 10000 后没有余数,则……」。j%10000 共有六次没有余数的情形:迭代数为 10000、20000、30000、40000、50000、60000 时。该打印输出会帮助我们很好地理解网络的学习进展。
代码 + str(np.mean(np.abs(l2_error)))) 取偏差的绝对值,然后求均匀数并打印出来,从而简化了打印过程。
现在我们已经知道预测结果(l2)间隔真值(y)的间隔,并打印了出来。但是,我们和城堡的间隔实在太远,我们要如何降落目前令人失落望的预测偏差 0.5,终极到达目的地呢?
一步步来。接下来,我们将理解调度网络的哪一部分才能改进下一次预测的结果,之后会谈论如何调度网络。