出处: Michael Nielsen的《Neural Network and Deep Learning》,点击末尾“阅读原文”即可查看英文原文。
本节译者:哈工大SCIR本科生 赵怀鹏 (https://github.com/zhaohuaipeng)
声明:我们将在每周一,周四,周日定期连载该书的中文翻译,如需转载请联系wechat_editors@ir.hit.edu.cn,未经授权不得转载。
-
使用神经网络识别手写数字
-
感知机
-
sigmoid神经元
-
神经网络的结构
-
用简单的网络结构解决手写数字识别
-
通过梯度下降法学习参数
-
实现我们的网络来分类数字
-
关于深度学习
反向传播算法是如何工作的
改进神经网络的学习方法
神经网络能够计算任意函数的视觉证明
为什么深度神经网络的训练是困难的
深度学习
正如你所见,这些数字实际上就是我们在章节开始所提到的作为挑战去识别的图像。当然,当我们测试我们的神经网络时,我们需要让它去识别不属于训练集中的数据。
MNIST数据集可以分为两个部分。第一个部分包含了60000个训练图像。这些图像是扫描了250人的手写数字,他们之中一半是来自美国人口普查局的员工,一半是来自于高中生。这些图像是有28乘28个像素点灰度图像。第二部分是10000个测试图像。同样它们也是28乘28的灰度图像。我们将会用这些测试数据去评估我们的神经网络识别效果如何。为了保证测试结果的准确性,这些测试数据也是来采样于另一个不同的250人的团体(尽管这些人也是来自美国人口普查局的员工和高中生)。这将会让我们确信我们的系统能够识别训练集外的手写数字图像。
我们将会用x去定义训练输入。将每一个训练输入x视为一个28×28=784-维的向量是很方便的。向量的每一个输入代表一个图像的一个像素点的灰度值。我们定义输出为y=y(x),每一个y 是一个 10-维的向量。举例来说,对于一个特定的描述数字x的训练图像,那么我们期待的输出是y(x)=(0,0,0,0,0,0,1,0,0,0)T。注意这里的T是转置的符号,它能将一个行向量变为列向量。
现在我们需要的是一个算法让我们去找到合适的权重和偏置能让所有的训练输入x都近似于y(x)。为了衡量我们是否达到目标,我们定义一个代价函数:
(6)
公式里面的w表示所有的权重的集合,b表示所有的偏置,n是训练数据的个数,a代表输出层的向量,这个和是包含了所有的训练输入x。当然输出a 取决于 x, w 和 b,但是为了保持符号的简洁性,我们没有明确的指出这种依赖性。符号||v||是指向量v的模。我们把C称为二次代价函数;有时我们也称它为均方误差或者MSE。通过代价函数的形式我们可以得知它是非负的,因为加和的每一项都是非负的。另外,代价函数C(w,b)会变小,e.g.C(w,b)≈0,简单来说就是对于所有的训练输入x,我们的输出a将会接近y(x)。因此我们的学习算法能很好的工作如果它能找到合适的权重和偏置能让C(w,b)≈0。从反方面来说就是如果C(w,b)很大,那么就说明学习算法效果很差。这意味着对于大量的输入来说,我们的结果a 与正确结果y(x) 相差很大。因此我们的训练算法的目标就是通过调整函数的权重和偏执来最小化代价函数C(w,b)。换句话说,我们想寻找合适的权重和偏置让代价函数尽可能地小。我们将通过梯度下降法来达到这个目的。
为什么要介绍平方代价(quadratic cost)呢?毕竟我们最初所感兴趣的内容不是对图像正确地分类么?为什么不增大正确输出的得分,而是去最小化一个像平方代价类似的间接评估呢?这么做是因为在神经网络中,被正确分类的图像的数量所关于权重、偏置的函数并不是一个平滑的函数。大多数情况下,对权重和偏置做出的微小变动并不会影响被正确分类的图像的数量。这会导致我们很难去刻画如何去优化权重和偏置才能得到更好的结果。一个类似平方代价的平滑代价函数能够更好地指导我们如何去改变权重和偏置来达到更好的效果。这就是为何我们集中精力去最小化平方代价,只有通过这种方式我们才能让分类器更精确。
即使我们知道了我们需要选择一个平滑的代价函数,你可能仍然会好奇为什么我们选择方程(6)中的二次函数。这是一个临时的决定么?是不是我们选择另一个不同的代价函数将会得到完全不同的权重和偏置呢?这是一个合理的担忧,稍后我们会再次提到这个代价函数并做一些修改。尽管如此,方程(6)中的二次代价函数能让我们更好地理解神经网络的基础,因此目前我们仍然坚持用它。
再次回顾一下,我们训练神经网络的目的是寻找合适的权重和偏置来最小化代价函数C(w,b)。这是一个适定性的问题,但是现在有很多让我们分散精力的结构-权重w和偏置b合理的解释,隐藏的σ函数,神经网络结构的选择,MNIST等等。事实证明我们可以忽略大部分问题,把精力集中在最小化方面。现在我们打算忘掉所有关于代价函数的具体形式,忘掉和神经网络有什么联系。现在想象我们仅仅是要去最小化一个给定的多元函数。我们打算介绍一种可以解决最小化问题的技术-梯度下降法。然后我们回到在神经网络中要最小化的函数上来。
假定我们要最小化某些函数,C(v)。它可能是任意的多元实值函数,v=v1,v2,…。注意我们将会用v去代表w和b以强调它可能是任意的函数-我们不会把问题局限在特定的神经网络上。假定C(v)有两个变量v1 和v2 : valley 我们想要的就是得到它的全局最小值。当然,对于上图的函数,我们能通过眼睛就可以找到最小值。这是因为我所展示的函数过于简单!一个一般的函数,C,可能是一个复杂的多元函数,通过眼睛可能找不到它的最小值。
一种解决这个问题的方式就是分析性去计算出它的最小值。我们可以计算出偏导,利用偏导去寻找函数C的极值点。运气好的话我们的函数C只有一个或者少数的几个变量。但是变量过多的话将是一个噩梦。在神经网络中我们通常会需要大量的变量-最大的神经网络的代价函数包含了数亿个权重和偏置。使用计算的方式不能再有效的工作了。
(我们只讨论了C只有两个变量的情况,如果我说“嗨,如果函数有多于两个变量怎么办?”。对于这种情况我只能说很抱歉。请相信我把C看成一个二元函数是有助于我们的理解的。善于思考数学通常也包含善于利用多种直观的图片,学习什么时候用什么图片合适。) 幸运的是有一个漂亮的类比预示着有一种算法能得到很好的效果。首先把我们的函数想象成一个山谷。我们想象又一个小球从山谷的斜坡滚落下来。我们的日常经验告诉我们这个球终会达到谷底。也许我们可以用这种思想来解决函数最小值的问题?我们随机地为小球选取一个起点,然后开始模拟小球滚落到谷底的运动。我们可以简单的通过计算C的导数(或者二阶导数)来模拟-这些导数将会告诉我们关于山谷“地形”的一切,这会引导我们的小球该如何下落。
基于上述的想法,你可能会认为我们会写下牛顿运动定理,考虑摩擦力,重力等等。其实我们不打算真的去实现这个小球的类比-我们只想要一个算法去最小化C,而不是真的去模拟它真实的物理定律。小球的鸟瞰能激发我们的想象而不是束缚我们的思维。因此与其去考虑麻烦的物理定律,不如我们这样问自己:如果我们扮演一天的上帝,能够构造自己的物理定律,能够支配小球的下落方式,那么我们将会采取什么样的物理定律来让小球能够始终滑落到谷底呢?
为了更精确的描述这个问题,让我们想象一下如果我们在v1方向移动一个很小的量Δv1并在v2方向移动一个很小的量Δv2将会发生什么呢。通过计算可以告诉我们C将会产生如下改变:
. (7)
我们将要寻找一种方式去选择Δv1和Δv2使得ΔC为负;比如,我们选择它们是为了让小球下落。为了搞清楚如何选择,有必要定义Δv来代表v变化的向量,Δv≡(Δv1,Δv2)T,T是转置符号。我们也定义C用来表示偏导的向量,。我们用∇C来表示梯度向量,比如:
(8)
待会我们将用Δv和∇C来重写ΔC。在这之前我想先说明一些令人困惑的关于梯度的事情。当第一次碰到梯度的符号∇C时,人们常会好奇为什么∇C符号是这样。∇究竟代表什么?事实上你可以把梯度仅仅看做一个简单的数学记号-方便用来表示偏导的向量-这样我们就不必写两个符号了。这样来看,∇仅仅是一面符号的旗帜,告诉你:“嗨,∇C是一个梯度向量。”也有很多其他的关于∇的解释(比如,作为一种微分符号),但我们不需要这种观点。
定义好上述符号之后,关于ΔC的表达式[(7)]能被重写成如下形式
ΔC≈∇C⋅Δv. (9)
这个表达式能很好地解释为什么∇C被称作梯度向量:∇C和C中v的变化密切相关,只是我们把它称为梯度罢了。但是这个式子真正让我们兴奋的是它让我们看到了如何选取Δ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,然后沿着梯度的反方向运动。就像下图一样: valley_with_ball 需要注意这种梯度下降的规则不代表真实的物理运动。在真实世界里,小球有势能,势能让小球可以在山谷斜坡上滚动,甚至顷刻间滚向山顶。只有加上摩擦力的影响才能保证小球会下落到谷底。不同的是,我们选择Δv的规则不一样,就像再说“立马下降!”。这仍然是一个寻找最小值的好办法。
为了使我们的梯度下降法能够正确地运行,我们需要选择足够小的学习速率η使得等式(9)能得到很好的近似。如果不那么做,我们将会以ΔC>0结束,这显然不是一个很好的结果。与此同时,我们也不能把η变得过小,因为如果η过小,那么梯度下降算法就会变得异常缓慢。在真正的实现中,η通常是变化的,以至方程(9)s能保持很好地近似度而且算法不会太慢。我们稍后会看这是如何工作的。
我已经解释了具有两个变量的函数C的梯度下降法。但事实上当C是其他多元函数时也能很好地运行。我们假设C是一个有m个变量v1,…,vm的多元函数。我们对自变量做如下改变Δv=(Δv1,…,Δvm)T,那么ΔC 将会变为
ΔC≈∇C⋅Δv, (12)
这里的∇C是向量
(13)
正如两个变量的例子一样,我们可以选取
Δv=−η∇C, (14)
并且我们也会保证公式[(12)中ΔC是负数。这给了我们一种方式从梯度中去寻找函数的最小值,即使C是任意的多元函数,我们也能重复运用下面的规则
v→v′=v−η∇C. (15)
你可以把这个更新规则看做梯度下降算法的定义。这给我们提供了一种方式去通过重复改变v来达到函数的最小值。然而这种规则并不总是有效的-有几件事能导致错误,让我们无法从梯度来求得函数C的全局最小值,这个观点我们会在后面的章节中讨论。但从实践方面来看,梯度下降法通常效果非常好,在神经网络中这是一种非常有效的方式去求代价函数的最小值,进而促进网络自身的学习。
事实上,有一种观念认为梯度下降法是求最小值的最优策略。我们假设努力去改变Δv来让C尽可能地减小,减小量为ΔC≈∇C⋅Δv。我们首先限制步长为固定值,即||Δv||=ϵ ,ϵ>0。当步长固定时,我们要找到使得C减小最大的下降方向。可以证明,使得∇C⋅Δv取得最小值的Δv为Δv=−η∇C,这里η=ϵ/||∇C||是由步长限制||Δv||=ϵ所决定的。因此,梯度下降法可以被视为一种通过在C下降最快的方向上做微小变化来使得C立即下降的方法。
练习
-
证明最后一段的断言。提示:利用柯西-斯瓦茨不等式。
-
我已经解释了当C是二元及其多元函数的情况。那如果C是一个单变量的函数呢?你能给出梯度下降法在一元函数的几何解释么?
人们已经研究出很多梯度下降法的变种,其中还包括一些去真正模拟真实物理运动的做法。这些模拟小球的变种有很多优点,但是也有一个主要的缺点:事实证明这种方法必须去计算C的二阶偏导,这可能代价非常大。为了理解为什么这种做法代价高,假设我们想求所有的二阶偏导
∂2C/∂vj∂vk。如果我们有上百万的变量vj,那我们必须要计算数万亿级别的二阶偏导!这的确会造成很大的计算代价。不过也有一些避免这些问题的技巧,寻找梯度下降方法的替代品也是个很活跃的研究领域。但在这本书中我们将主要用梯度下降法(包括变种)去训练我们的神经网络。
我们怎么用梯度下降法去训练我们的神经网络呢?方式就是利用梯度下降法去寻找权重wk和偏置bl 能减小[(6)]式中的代价函数。为了弄清楚具体是如何工作的,我们将用权重和偏置代替变量vj来重申梯度下降算法的更新规则。我们的“位置”对应wk和bl,梯度向量∇C对应∂C/∂wk和∂C/∂bl。申明了梯度下降中成分之后,我们得到(16)
(17)
通过重复更新我们能“滚到山底”,有望能找到代价函数的最小值。换句话说,这个规则能用在神经网络的学习中。
应用梯度下降规则有很多挑战。我们将在下一章深入讨论。但是现在我想提及一个问题。为了理解问题是什么,我们先回顾[(6)]中的二次代价函数。注意这个代价函数有着如下的形式,也就是说,它是每个样本代价Cx≡||y(x)−a|| / 22的平均值。事实上,为了计算梯度∇C,我们需要为每个训练样本x单独地计算梯度值∇Cx,然后求平均值,。不幸的是,当训练输入过大时会花费很长时间,这样会使学习变得相当缓慢。
有种叫做随机梯度下降(SGD) 的算法能够用来加速学习过程。想法就是通过随机选取小量输入样本来计算∇Cx,进而可以计算∇C。采取少量样本的平均值可以快速地得到梯度∇C,这会加速梯度下降过程,进而加速学习过程。
更准确地说,SGD是随机地选取小量的m个训练数据。我们将选取的这些训练数据标号X1,X2,…,Xm,并把它们称为一个mini-batch。我们选取的m要足够大才能保证∇CXj的平均值才能接近所有的平均值∇Cx,也就是说,
(18)
这里的第二项是整个训练数据的和。交换两边我们可以得到
(19)
证实了我们可以通过计算随机选取mini-batch的梯度来估计整体的梯度。
为了将这种想法更确切地联系到神经网络的学习中来,假设用wk和bl分别代表权重和偏置。SGD就是随机地选取大小为一个mini-batch的训练数据,然后去训练这些数据,
(20)
(21)
这个和就是当前mini-batch中每个Xj的梯度值。然后我们再随机选取另一个mini-batch去训练,直到我们用完了所有的训练数据,这就完成了一次迭代训练。这样我们就会重新开始下一轮迭代。
值得一提的是,关于调节代价函数和mini-batch去更新权重和偏置有很多不同的约定。在(6)式中,我们通过因子1/n来缩放全部的代价函数。人们通常忽略1/n,直接计算单独训练样本代价之和,而不是求平均值。这对我们不能提前知道训练数据集大小的情况下特别有效。这可能发生在有更多的训练数据是实时加入的情况下。同样,mini-batch的更新规则(20)和(21)有时也会舍弃1/m。从概念上这也会有一点区别,因为它等价于重新调节学习速率η。但在对不同工作进行详细比较时,它的价值是值得关注的。
我们能把SGD想象成一场民主选举:使用小规模的mini-batch计算梯度,比使用整个训练集计算梯度容易得多,就如开展一次民意调查比举行一次完整的选举容易得多。举个例子,在MNIST中有60,000个测试数据,我们选取mini-batch的长度为m=10,这样,计算梯度的过程就加速了6,000倍!当然,这个估计可能并不准确——仍然会存在统计波动——但也没必要准确:我们只关心在某个方向上移动可以减少C,这意味着我们没必要准确去计算梯度的精确值。事实上,SGD在神经网络的学习中被广泛使用的十分有效的技术,它也是本书中展开的大多数学习技术的基础。。
练习
-
梯度下降一个比较极端的版本就是让mini-batch的大小变为1。这就是说,给定一个输入x,我们通过规则和
更新权重和偏置。当我们选取另一个训练数据时也做同样的处理。其他的训练数据也做相同的处理。这种处理方式就是online learning。在online learning中,神经网络在一个时刻只学习一个训练数据。说出online learning和mini-batch为20的SGD对比的一个缺点和一个优点。
让我们讨论一个令刚接触梯度下降的人困惑的问题来总结这部分的内容。在神经网络中,代价函数C是一个关于所有权重和偏置的多元函数,因此在某种意义上来说,就是在一个高维空间定义了一个平面。有些人可能会那么想:“嗨,我必须要看见其他多出的维度”。他们会开始疑惑:“我不能想象出四维空间,更不用说五维(或者五百万维)”。是不是他们缺少某种只有超级数学家才有的超能力?当然不是。即使大多数专业的数学家也不能想象出四维空间的样子。他们会用一些其他的方式来表示什么在发生。正如我们上面所做的那样,我们可以用代数(而不是几何)来表示ΔC如何变化才能让C减少。善于思考高维的人会在脑中做一些思想实验;我们的代数技巧也是一个例子。这些方法可能不如观察三维那么直观,但我们熟悉这些方法之后会帮助我们思考更高维度。我不想在这里详细展开,如果你感兴趣,你可以读一些关于数学家如何思考高维空间的书。我们讲的一些技术可能会有点复杂,但大多数内容还是比较直观的,任何人都能熟练掌握。
下一节我们将介绍“实现我们的网络来分类数字”,敬请关注!
-
“哈工大SCIR”公众号
-
编辑部:郭江,李家琦,徐俊,李忠阳,俞霖霖
-
本期编辑:李家琦
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:《神经网络和深度学习》系列文章六:通过梯度下降法学习参数 - Python技术站