梯度下降学习算法
现在我们设计了一个神经网络,它怎样能去学习识别数字呢?第一件事情是我们需要一个数据集去学习——被称为训练数据集。我们将使用MNIST的数据集,它有上万张手写数字的扫描图片,并且还有它们的正确分类。MNIST的名字来自这样一个事实,这是一个NIST(美国国家标准与技术研究院)收集的两个数据集子集的修改。下面是来自MNIST的几张图片: 。
正如你所看到的,这些数字实际上和本章开头要识别的那些一样。当然,测试我们网络的时候,我们将不会让它去识别训练集里的图片!
MNIST的数据来自两部分。第一部分有60,000张图片被用来作为训练数据。这些图片扫描
自250个人的手写样本,他们中的一半是美国人口普查局的员工,另一半是高校学生。这些图片是灰色的,大小为28x28像素。MNIST数据集的第二部分有10,000张图片被用来做为测试数据。也是28x28的灰色图片。我们将使用测试数据云评估我们的神经网络数字识别的怎么样。为了有一个好的测试效果,与原始训练数据相比,测试数据来自250个不同的人(虽然仍是人口普查局员工和高校学生中的一组人)。这帮助我们相信我们的系统可以识别出训练时不曾见过人写的数字。
我们将使用符号表示一个训练输入。把每一个训练输入当作是一个维向量将会带来很多便利。向量里的每一项表示图片里一个像素的灰度值。我们将对应的期望输出表示为,其中是一个10维向量。例如,如果一个个别的训练图像,画的是6,那么来自网络的期望输出是。注意这里的是转换操作,将一个行向量变成一个普通(列)向量。
我们期望有一个算法能让我们找到权重和偏移量,所以对于所有的训练输入网络的输出最好能近似于。为了量化我们离目标的程度,我们定义一个成本函数(旁注:有时被称为损失或目标函数。我们在本书中使用成本函数这个术语,但你需要注意其他的术语,因为它经常在学术论文或其他神经网络的讨论中被用到):
这里,表示网络里所有权重的集合,是所有的偏移量,训练输入的总数量,是当输入为时网络的向量输出,最后求得是所有训练输入的和。当然,输出是依赖于,和的,但为了能让符号简单一些,我没有明确地指出这些依赖。符号仅仅是为了表示向量通常的长度函数。我们称为二次成本函数;它也时常被当作均方误差或MSE。通过检查这个二次成本函数的形式,我们发现是非负的,因为在和里的每一项都是非负的。此外,成本变小,也就是,,准确的讲就是约等于所有训练输入对应的输出。所以我们的训练算法如果能找到权重和偏移量让,那么它就是一个好的算法。相对的,当比较大是不太好的——这意味着没有接近很多输入的输出。所以我们训练算法的目标就是让成本变小的关于权重和偏移量的函数。换句话说,我们想要找一组权重和偏移量,能让成本尽可能的小。我们将使用一个被称为梯度下降的算法。
为什么要介绍二次成本函数呢?毕竟,我们主要的兴趣点在于通过网络分类正确的图片数量不是吗?我们为什么不直接尝试让这个数量最大,而是让像那个二次成本函数的间接度量值最小呢?问题的原因在于 分类正确的图片数量不是一个关于网络里权重和偏移的平滑函数。多数情况下,对权重和偏移做微小修改根本不会对正确分类的训练图片数量有任何变化。这让通过改变权重和偏移量来优化网络变得非常困难。如果我们用一个像上面那个二次成本函数一样平滑的成本函数将很容易通过改变权重和偏移量来改进成本。这就是为什么我们首先聚焦于最小化二次成本函数,之后我们将检查分类的正确率。
即使确定了我们需要一个平滑的成本函数,你可能仍然会怀疑为什么要选择公式(6)的二次函数。它是不是一个临时的选择?也许选择一个不同的成本函数我们将得到完全不同的权重和偏移量的集合?这是合理的忧虑,后面我们将重新审视成本函数,并做一些修改。尽管如此,公式(6)的二次成本函数对于我们理解神经网络是非常合适的,所以我们现在将仍然使用它。
我们的目标更新成训练一个神经网络找到使二次成本函数最小的权重和偏移量。这是一个适定问题,但当前要确定的分散在不同的结构中——和对应的权重和偏移量,隐含的函数,网络选择的结构,MNIST等等。事实证明我们可以理解很多被忽略的结构,我们只关注最小化方面。所以现在我们要忘记上面特别指出的成本函数的形式,与神经网络的联系等等。相反,我们会想象,我们只是有一个包含很多变量的函数,我想让这个函数的值最小。我们要开发一项叫梯度下降的技术,它可以被用来解决很多最小化问题。然后我们将回来看为神经网络而选函数的最小化问题。
好,假设我们在尝试求的最小值。这些可能是任何实值函数的一些变量,。请注意我已经把和的符号替换成了,这样是为了强调可以是任何函数——我们并不是特别在神经网络的范围内讨论。为了求的最小值,可以想像是一个只有两个变量的函数,叫做和:
我们要做的是找到全局最小的地方。现在,当然,上面所描绘的函数,我们可以通过看图片找到最小值。这样的话,可能是展示的函数看上去太简单了!通常的函数,可能是一个有多个变量的复杂函数,它不可能通过直接观察就能找到全局最小值。
解决问题的一种方式是使用微积分来分析找出最小值。我们可以计算导数并尝试用它找出的极值位置。够幸运的话是一个只有几个变量的函数,但当有很多变量的时候这将是一场恶梦。而且对神经网络来说我们将会经常想要许多的变量——最大神经网络的成本函数在极端复杂的方式下有数十亿的权重和偏移量。使用微积分来求最小值不太好用!
(下了上面的断言后,我们将通过想象为只有两个变量的函数来获取洞察力,我已经在两个段落里讲过两次,如果你说“但如果它是一个比两个变量多很多的函数呢?”,那我感到很抱歉。请相信我,将函数想象成只有两个变量将对我们有帮助。只是有时会发生图像法失败,最后两个段落将处理这种问题。好的数学思想方式就是经常使用一些直观的图像,并学着什么时候适合用哪一个,什么时候不适合。)
OK,所以用微积分解决不了问题。幸运的是有一个相似的算法十分好用。我们开始将我们的函数看成一种山谷。如果你在图上方稍微斜一点,这并不难。我们想像有一个球从山谷的坡滚落。我们的常识会告诉我们那个球将最终滚到山谷的底部。或许我们用这个想法作为一种寻找函数最小值的方式?我们随机选为一个(假设的)球选一个开始位置,然后模拟球滚向谷底的动作。我们可以通过计算导数(也可能是二次层数)来简单模拟——这些层数将告诉我们需要了解的山谷在当前位置下的“形状”,也就是我们的球应当怎样滚动。
基于我刚才所写的,你可能会猜想我们是不是要为那个球写一个牛顿的运动方程,考虑上摩擦和重力等因素的影响。实际上,我们不会把球滚动类比的如此严重,我们设计的是求最小值的算法,不是开发一个精确的物理学模拟系统!用球的视角是为了促进我们的想象,而不是束缚我们的思想。所以与其掉进麻烦的物理细节里,还不如让我们简单得问自己:如果有一天我们是上帝,可以定义我们自己的物理定律,指示那个球该如何滚动,那什么样的定律可以让球总是能滚动到谷底?
为了让这个问题更实际一些,让我们考虑当把球在方向上移到很小量,在方向上移到很小量时会发生什么。计算告诉我们将作如下改变:
我们将寻找一种选择和的方式,让变成负值;也就是,我们这样选择后,球就会滚向谷底。为了指明怎样作出这样的选择,我们声明是变化的向量,,这里的也是转置操作,将行向量变为列向量。我们再定义的梯度为该向量的偏导数。我们通过表示梯度向量的偏导数,也就是:
一会儿我们将重写改变项里的和梯度,。开始做这个之前,然而,我想澄清一些有时会让人们在梯度方面迷惑的事情。当第一次见到这个符号的时候,人们有时会怀疑这个符号到底是什么东西。准确的说到底是什么意思?实际上,你完全可以把当作一个独立的数学对象——上面定义的向量——用两个符号书写而成。从这个角度来看,只是一个强调标记,告诉你“嗨,是一个梯度向量”。更深远的看法是可以被看成是一个有自身意义的独立数学实体(例如,作为一个微分运算符),但我们并不需要这样的看法。
有了这些定义,关于的表达式(7)可以被重写成
这个方程帮我们解释了为什么被叫做梯度向量:关系着的改变到的改变,就像我们期望叫做梯度的东西一样。但这个方程真正给力的地方是,它让我们看到怎样选择可以让变成负数。比较特殊的是,假设我们选择
,这里的是一个很小的正参数(被称为学习率)。这样方程(9)告诉我们。因为,这保证了,也就是说,如果我们按照方程(10)的指示改变的话,将一直是减少的,从不会增加。(当然这里是方程(9)的极限近似值)。这正是我们想要的性质!所以在我们的梯度下降算法里,我们把方程(10)定义为球的“运动规则”。就是说,我们将用方程(10)来计算的值,然后移到球的位置通过这个结果:
。一会儿我们将再用一次这样的更新规则,来做别的移到。如果我们一直这样做下去,一次又一次,将一直减小直到——我们希望的——我们将达到一个全局最小值。
总结,梯度下降算法的工作方式就是重复的计算梯度,然后向相反的方向移动,沿着山谷的斜坡“坠落”。我们可以像下面这样显示
注意这里的梯度下降规则并不是复制了真正的物理运动。在现实里一个球是有动量的,它可以让球沿着斜坡滚动,或者甚至(暂时地)向上滚。它只有在摩擦力设定的效果下这个球才能保证滚下山谷。与之相比,我们选择的规则只是说“下降,现在”。这仍然是一个完美寻找最小值的规则。
为了让梯度下降能准确执行,我们需要选择一个足够小的学习率让方程式(9)能够比较好的近似。如果不这样做,我们可能会以告终,这显然不靠谱!同时,我们也不希望太小,因为这样会使的改变很小,导致梯度下降算法执行的非常缓慢。在实际的实现里,是经常变动的,这样方程式(9)能保留一个好的近似,同时算法也不会太慢。我们将在后面看到是怎样做。
我已经阐述了当是一个只有两个变量的函数时的梯度下降。但实际上,即使有很多变量也照样可行。假设特定的函数有个变量,。那么通过一个小的改变使变化的量就等于
,这里的梯度是一个向量
就像两个变量的情况一样,我们可以选择
,我们可以保证对的近似表达式(12)将是负值。这就给我们一种沿着梯度到达最小值的方式,即使是有很多变量,通过重复执行更新规则
你可以认为这个更新规则就是定义了梯度下降算法。它通过重复改变的位置来寻找函数的最小值。这个规则也并不总是好用的——很多东西可以引发错误并阻止梯度下降去寻找的全局最小值,这一点我们将在后面的一章来探究。但实际上梯度下降法通常运行的非常好,并在神经网络里我们将看到它有力的最小化了成本函数,这帮助了网络的学习。
事实上,这给人一种感觉,梯度下降算法是寻找最小值的一种最佳策略。假设,我们尝试在某处移动以便尽可能的减小。这等价于去最小化。我们将限制移动的幅度,也就是用一些小的固定值。换句话说,我们想让移动是有着固定幅度的一小步,并且我们尝试找到一个能最大限度减少的移动方向。它可以这样证明,最小化中的选择是,其中是由常量决定的。所以梯度下降算法可以可以被看成是一种在最大限度立即减小的方向上小步前进的方式。
练习
证明最后一章的断言。提示:如果你对柯西-施瓦茨不等式不熟悉的话,你会发现熟悉它将会对你帮助很大。
我阐述了当是一个二元和多元函数时的梯度下降算法。那当只是一个一元函数时会发生什么呢?你能提供一个梯度下度算法在一维下的几何解释吗?
人们已经研究了许多梯度下降算法的变种,包括一些十分接近模拟一个真正的物理球的变种。这些模拟球的变种有一些进展,但也有一个主要的缺点:它必须要计算的二阶偏导数,这非常耗时。为了看明白为什么它如此耗时,假设我们想计算所有的二阶偏导数。如果有数百万个这样的变量,那么我们可能需要计算数万亿次(就是,一百万的平方)【实际上差不多是万亿次的一半,因为,你能明白吧】。这将会是非常耗时的计算。按照这种说法,有些技巧可以避免此类问题,并且寻找梯度下降算法的替代选择是一个活跃的调查领域。但本书我们将用梯度下降算法(和其变种)做为我们神经网络学习主要的算法。
我们怎样应用梯度下降算法来在神经网络里进行学习呢?主要思想是使用梯度算法去寻找权重和偏移量,这些让在方程式(6)中的成本函数最小化的参数。为理解它的运作方式,让我们回顾下梯度下降算法的更新规则,使用权重和偏移量来替换变量。换句话说,我们的“位置”现在由和构成,梯度向量与和相关。使用上面的构成部分写出梯度下降算法的更新规则如下:
通过重复执行此更新规则,我们将“滚下山底”,并且很有希望能找到成本函数的最小值。换句话说,这个规则可以被神经网络用来学习。
在使用梯度下降算法时有许多挑战。我们将在最后一章做深入探讨。但现在我只想提一个问题。为了理解问题是什么,让我们回头看下方程工(6)的二次成本函数。注意这个成本函数的形式,这是每一个训练样本的平均成本。实际上,为了计算梯度,我们需要去分别计算每一个训练输入的梯度,然后取它们的平均值。不幸的是,当训练样本的量非常大时,这将花费很长时间,学习效率也因此降低。
一种叫做随机梯度下降的算法可以加快学习速度。这种算法是通过计算一些随机选择的少量训练样本输入的来估算梯度。通过求这些少量样本的平均值,最后我们可以迅速得到真正梯度的好的近似值,这将加快梯度下降算法,学习效率也将提高。
为了使这些算法更加准确,随机梯度下降算法随机挑选很小的数字个训练输入。我们这些随机的训练输入标记为,并将它们做为一个小批次。假如样本的大小足够的大,我们期望的平均值能约等于的平均值,也就是,
,这里第二个求和是对于整个训练数据说的。交换一下等式的两边可以得到
,求证我们可以通过只计算随机挑选的小批次的梯度,来估计整体的梯度。
为了让它与神经网络学习之间的联系明显一些,假设和表示我们神经网络的权重和偏移量。然后,随机梯度下降算法通过随机挑选训练输入集的一个小批次,并用其进行训练,
这里的和求得是当前小批次里的训练样本集。然后我们再随机挑选另外一个小批次并用其进行训练。诸如此类,直到我们用尽了整个训练输入集,这被叫做完成了训练的一代。在这个时间点我们开始一代新的训练。
顺便,值得注意的是对于惯例的成本函数和小批次更新权重和偏移量许多版本的扩展。在方程(6)中我们通过一个因子来缩放整个成本函数。人们有时会忽略这个,用求所有单个训练样本成本的和代替求平均。这对于不能预先知道训练样本总数量时特别有用。例如,这会发生在许多训练数据是实时生成的。同时,用相同的方式,小批次更新规则(20)和(21)有时删除求和项前面的。在概念上这会造成一点不同,因为它相当于重新调节了学习率。但值得看一看不同操作下细节的不同。
我们可以把随机梯度下降算法看成是政治民意测验:对小批次进行取样比全批次的执行梯度下降要容易的多,就像实行民意测验要比做一次全民选举要容易一样。例如,如果我们大小是的训练子集,像在MNIST里,然后选一个大小为的小批次,这意味着我们将在梯度估计上获得倍的加速!当然,这种估计也不是完美的——会有统计波动——但它不需要完美:我们真正关心的是找到一个能帮助减小的移动方向,也就是说我们不需要计算梯度的准确值。在实践中,随机梯度下降算法被普遍应用,是神经网络的有力技术,也是本书里大部分学习技术的基础。
练习
- 一个极端版本的梯度下降算法使用小批次的大小仅为1。就是说,给出一个训练输入,,我们按照下面的规则更新权重和偏移量和。 然后我们选择另一个训练输入,再更新输入和偏移量。以此类推,重复。这个过程被称为在线或增强学习。在在线学习中,一个神经网络的学习每次只是来自一个训练输入(就像人类一样)。对比批次大小为20的随机梯度下降算法,说一下在线学习的一个优点和一个缺点。
让我通过讨论人们刚开始用梯度下降算法经常会犯的错误来结束本章。在神经网络里成本,当然,是一个有很多变量的函数——所有的权重和偏移量——所以在某些场景下会在非常高的维度空间里定义一个平面。有一些人会纠结于:“嗨,我不得不可视化所有这些额外的维度”。然后他们会开始担心:“我无法想像四个维度,更何况是五个(或五百万个)”。是否他们缺失了某些特殊的能力,这些能力只有特别牛的大数学家才拥有?当然,答案是否定的。即使是大部分专业数据家也不能特别好的可视化四个维度,如果真要这样做的话。他们使用的技巧是开发别的表达方式。这正是我们上面所有做的:我们使用一个代数符号(而不是视觉展现)表示,来表示怎样移动会减小。沿着这些思路善于思考的人在高维度方面有一个知识体系,这里包含许多不同的技术;我们的代数技巧只是其中的一个样例。这些技术可能没有我们习惯了的三个维度下的可视化那样简单,但只要你用这些技术构造一个体系后,你可以在高维方面的思考变得非常好。我不打算再讲更多的细节,但如果你感兴趣的话,可以看一下一些专业数学家在高维技术方面的讨论。虽然有些讨论相当复杂,但大部分好的内容浅显易懂,能被任何人掌握。