【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

目录

简介

第一章-使用神经网络识别手写数字

                     第一节-感知机

                     第二节-sigmoid神经元

                     第三节-神经网络的结构

                     第四节-用简单的神经网络识别手写数字

                     第五节-通过梯度下降法学习参数

                     第六节-实现我们的手写体数字分类神经网络

                     第七节-向深度学习进发!

译者注

                哈工大原版翻译地址:https://hit-scir.gitbooks.io/neural-networks-and-deep-learning-zh_cn/content/

                文章原版地址:《Neural Networks and Deep Learning》http://neuralnetworksanddeeplearning.com/


我们已经设计出了一个神经网络结构,现在面临的问题是,它应该如何学习识别数字呢?首先,我们需要一个待学习的数据集——即所谓的训练数据集。我们下面会使用MNIST数据集,其中包含了大量扫描得到的手写数字图像以及它们对应的数字。MNIST 数据集是由NIST(the United States' National Institute of Standards and Technology,美国国家标准与技术研究院)根据收集得到的两个数据集经修改后得到的子数据集构成,所以取名叫 MNIST。下面是 MNIST 中的一些图像:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

正如你所见,这些数字实际上就是我们在本章开始所提到的图像。当我们测试我们的神经网络时,我们需要让它去识别训练集之外的数据。

MNIST 数据集可以分为两个部分。第一个部分包含了 60,000 个用于训练的图像。这些图像是扫描了 250 个人的手写数字得到的,他们之中一半是来自美国人口普查局的员工,另一半是高中生。这些图像是 28 乘 28 个像素点灰度图像。MNIST 的第二个部分是 10,000 个用于测试的图像,它们同样也是 28 乘 28 的灰度图像。我们将会用这些测试数据去评估我们的神经网络的识别效果。为了保证测试结果的准确性,这些测试数据是采样于另一个不同的、250人的样本(尽管这些人也是美国人口普查局的员工和高中生)。这保证了我们的系统能够识别训练集之外的手写数字图像。 

我们用x去定义训练输入。为了方便起见,我们将每一个训练输入x视为一个28×28=784维的向量。向量中的一个元素代表图像的一个像素点的灰度值。我们定义输出为y=y(x),每一个y是一个10维的向量。举例来说,对于一个数字6的训练图像x,我们期待的输出是【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数。这里的【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数是转置符号,它能将一个行向量变为列向量。

现在我们需要一个算法能让我们找到合适的权重和偏置,从而对所有的训练输入为x的输出都近似于y(x)。为了衡量我们当前取得的结果距离目标结果的好坏程度,我们定义一个代价函数

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

公式里面的w表示所有的权重的集合,b表示所有的偏置,n是训练数据的个数,a代表x作为输入时输出层的向量,求和针对所有的训练输入x。 显而易见,输出a取决于x, w和b,但是为了保持公式的简洁性,我们没有明确指出这种依赖性。符号∥v∥是指求向量v的范数。【如果不理解什么是向量范数可以看看这篇文章:白话理解向量范数】这时,我们称C为二次代价函数;有时我们也称它为平方误差或者MSE。通过代价函数的形式我们可以得知C(w,b)是非负的,因为加和的每一项都是非负的。另外,当所有的训练输入x的输出a基本都等于y(x)时,代价函数C(w,b)的值会变小,可能有C(w,b)≈0。因此如果我们的学习算法可以找到合适的权重和偏置使得C(w,b)≈0,那么这就是一个好的学习算法。反过来来说,如果C(w,b)很大,那么就说明学习算法的效果很差——这意味着对于大量的输入,我们的结果a与正确结果y(x)相差很大。因此,我们的训练算法的目标就是通过调整函数的权重和偏置来最小化代价函数C(w,b)。换句话说,我们想寻找合适的权重和偏置让代价函数尽可能地小。我们将使用一个叫做梯度下降法(gradient descent)的算法来达到这个目的。

为什么要介绍平方损失(quadratic cost)呢?毕竟我们最初所感兴趣的内容不是对图像正确地分类吗?为什么不增大正确输出的得分,而是去最小化一个像平方损失类似的间接评估呢?这么做是因为在神经网络中,被正确分类的图像的数量关于权重、偏置的函数并不是一个平滑的函数。大多数情况下,对权重和偏置做出的微小变动并不会影响被正确分类的图像的数量。这会导致我们很难去刻画如何去优化权重和偏置才能得到更好的结果。一个类似平方损失的平滑代价函数能够更好地指导我们如何去改变权重和偏置来达到更好的效果。这就是为何我们集中精力去最小化平方损失,只有通过这种方式我们才能让分类器更精确。

即使知道了我们需要选择一个平滑的代价函数,你可能仍然会好奇为什么我们选择方程(6)中的二次函数。这是一个拍脑袋的决定吗?是不是我们选择另一个不同的代价函数将会得到完全不同的权重和偏置呢?这是一个合理的问题,稍后我们会再次提到这个代价函数并做一些修改。尽管如此,方程(6)中的平方代价函数能让我们更好地理解神经网络的基本原理,因此我们目前先用它。

再次回顾一下,我们训练神经网络的目的是寻找合适的权重和偏置来最小化平方代价函数C(w,b)。这个问题已经明确定义好了。但是现在还存在很多让我们分散精力的问题——对权重w和偏置b合理的解释,隐藏在背后的σ函数,神经网络结构的选择,MNIST 等等。实际上我们可以先忽略这些问题,把精力集中在最小化的问题上。现在让我们忘掉代价函数的具体形式,忘掉神经网络的结构,忘掉其它一切。现在想象我们仅仅是要去最小化一个给定的有很多变量的函数。我们即将要介绍一种可以解决最小化问题的技术,称作梯度下降法。然后我们再回到要在神经网络中最小化的函数上来。

假定我们要最小化某些函数,C(v)。它可能是任意的多元实值函数,v=v1,v2,…。注意我们将会用v去代表w和b以强调它可能是任意的函数——我们不会把问题局限在神经网络中。假定C(v)有两个变量v1 和v2:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

我们的目标就是找到C在何处取得全局最小值。当然,对于上图的函数,我们能通过肉眼就可以找到最小值。这是因为我所展示的函数简单了!一个一般的函数C,可能是一个复杂的多元函数,通过肉眼通常找不到它的最小值。 

一种解决方法就是用数值计算的方法去计算出它的最小值。我们可以计算出偏导,利用偏导去寻找函数C的极值点。运气好的话我们的函数C只有一个或者少数的几个变量。但是变量过多的话将是一个噩梦。在神经网络中我们通常会需要多得多得多的变量——最大的神经网络的代价函数包含了数亿个权重和偏置。根本没法使用数值计算的方法!

(我们只讨论了C只有两个变量的情况,如果我说「嗨,如果函数有多于两个变量怎么办?」。对于这种情况我只能说很抱歉。请相信我把C看成一个二元函数是有助于我们的理解的。善于思考数学通常也包含善于利用多种直观的图片,学习什么时候用什么图片合适。)

所以,数值计算的方法没法完成这个任务了。幸运的是,有一个漂亮的类比预示着有一种算法能得到很好的效果。首先把我们的函数想象成一个山谷。我们想象有一个小球从山谷的斜坡滚落下来。我们的日常经验告诉我们这个球终会达到谷底。也许我们可以用这种思想来解决函数最小值的问题?我们随机地为小球选取一个起点,然后开始模拟小球滚落到谷底的运动过程。我们可以简单的通过计算C的导数(或者二阶导数)来模拟这个过程——这些导数将会告诉我们关于山谷「地形」的一切信息,从而告诉我们的小球该如何下落。

基于上述的想法,你可能会认为我们会写下牛顿运动定理,考虑摩擦力、重力等等。其实我们不打算真的去实现这个小球的类比——我们只想要一个算法去最小化C,而不是真的去模拟它真实的物理定律。小球的视角能激发我们的想象而不是束缚我们的思维。因此与其去考虑麻烦的物理定律,不如我们这样问自己:如果我们扮演一天的上帝,能够构造自己的物理定律,能够支配小球的下落方式,那么我们将会采取什么样的物理定律来让小球能够始终滑落到谷底呢?

为了更精确地描述这个问题,让我们想象一下如果我们在v1方向移动一个很小的量Δv1,并在v2方向移动一个很小的量Δv2将会发生什么呢。通过计算可以告诉我们C将会产生如下改变:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

我们将要寻找一种方式去选择Δv1和Δv2使得ΔC为负,因为负值能够让小球下落。为了搞清楚如何选择,我们有必要定义Δv,它是描述v变化的向量,【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 ,T是转置符号。我们也定义C用来表示偏导的向量,【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 。我们用∇C来表示梯度向量:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

 待会我们将用Δv和∇C来重写ΔC。在这之前我想先说明一些令人困惑的关于梯度的事情。当第一次碰到梯度的符号∇C时,人们常会好奇为什么∇C符号是这样。∇究竟代表什么?事实上你可以把梯度仅仅看做一个简单的数学记号——一个方便用来表示偏导的向量——这样我们就不必写两个符号了。这样来看,∇仅仅是一面旗帜,它告诉你:「嘿,∇C是一个梯度向量」。也有很多其他的关于∇的解释(比如,作为一种微分符号),但我们不需要这种观点。

定义好上述符号之后,关于ΔC的表达式(7)能被重写成如下形式

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

这个表达式能很好地解释为什么∇C被称作梯度向量:∇C和C中v的变化密切相关,只是我们把它称为梯度罢了。 但是这个式子真正让我们兴奋的是,它让我们看到了如何选取Δv才能让ΔC为负数。假设我们选取

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

这里的η是个很小的正数(就是我们熟知的学习率(learning rate))。等式(9)告诉我们 【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,由于 【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数这保证了 【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,例如,如果我们以等式(10)的方式去改变v,那么C将一直会降低,不会增加。(当然,要在(9)式的近似约束下)。这就是我们想要的特性!因此我们把(10)式看做梯度下降算法的「运动定律」。也就是说,我们用(10)式计算Δv,把小球位置v移动:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

 

然后我们可以迭代地去更新。如果我们反复那么做,那么C会一直降低到我们想要寻找的全局最小值。

总结一下,梯度下降算法工作的方式就是重复计算梯度∇C,然后沿着梯度的方向运动,即沿着山谷的斜坡下降。就像下图一样:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

需要注意这种梯度下降的规则不代表真实的物理运动。在真实世界里,小球有势能,势能让小球可以在山谷斜坡上滚动,甚至顷刻间滚向山顶。只有加上摩擦力的影响才能保证小球会下落到谷底。我们选择Δv的规则不一样,我们就好像在命令「立马下降!」。这仍然是一个寻找最小值的好办法! 

 

为了使我们的梯度下降法能够正确地工作,我们需要选择足够小的学习速率η使得等式(9)能得到很好的近似。如果不那么做,我们将会以 【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数结束,这显然不是一个很好的结果。与此同时,我们也不能把η设得过小,因为如果η过小,那么梯度下降算法就会变得异常缓慢。在真正的实现中,η通常是变化的,从而方程(9)能保持很好地近似度同时保证算法不会太慢。我们稍后会看这是如何工作的。

我已经解释了具有两个变量的函数C的梯度下降法。但事实上当C是其他多元函数时也能很好地运行。我们假设C是一个有m个变量 【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数的多元函数。我们对自变量做如下改变 【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,那么ΔC将会变为:

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

这里的∇C是 

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

正如两个变量的例子一样,我们可以选取

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

并且我们也会保证公式(12)中ΔC是负数。这使得我们能够随着梯度得到函数的最小值,即使C是任意的多元函数,我们也能重复运用下面的规则 

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

你可以把这个更新规则看作梯度下降算法的定义。这给我们提供了一种方式去通过重复改变v来找到函数C的最小值。然而这种方式并不总是有效的——有几种情况能导致错误的发生,使得我们无法从梯度得到函数C的全局最小值,这种情况我们会在后面的章节中讨论。但在实践中,梯度下降法通常效果非常好,在神经网络中这是一种非常有效的方式去求代价函数的最小值,从而帮助神经网络学习。 

 事实上,有一种观念认为梯度下降法是求最小值的最优策略。我们假设努力去改变Δv来让C尽可能地减小,减小量为ΔC≈∇C⋅Δv。我们首先限制步长为固定值,即【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数。当步长固定时,我们要找到使得C减小最大的下降方向。可以证明,使得∇C⋅Δv取得最小值的Δv为Δv=−η∇C,这里【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数是由步长限制【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 所决定的。因此,梯度下降法可以被视为一种通过在C下降最快的方向上做微小变化来使得C立即下降的方法。

练习

  • 证明最后一段的断言。提示:利用柯西-斯瓦茨不等式

  • 我已经解释了当C是二元及其多元函数的情况。那如果C是一个单变量的函数呢?你能给出梯度下降法在一元函数的几何解释么?

人们已经研究出很多梯度下降法的变种,其中还包括一些去真正模拟真实物理运动的做法。这些模拟小球的变种有很多优点,但是也有一个主要的缺点:这些方法必须去计算C的二阶偏导,这可能代价非常大。 为了理解为什么这种做法代价高,假设我们想求所有的二阶偏导【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数如果我们有上百万的变量vj,那我们必须要计算数万亿级别的二阶偏导!这的确会造成很大的计算代价。不过也有一些避免这些问题的技巧,寻找梯度下降方法的替代品也是个很活跃的研究领域。但在这本书中我们将主要用梯度下降法(包括变种)去训练我们的神经网络。

我们在神经网络中应用梯度下降法呢?方式就是利用梯度下降法去寻找权重【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数和偏置【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 能减小(6)式中的代价函数。为了弄清楚具体是如何工作的,我们将用权重和偏置代替变量【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数来重新描述梯度下降算法的更新规则。我们描述「位置」的元素是【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,梯度向量【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数对应【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 。申明了梯度下降中成分之后,我们得到

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

通过重复更新我们能「滚到山底」,从而有望能找到代价函数的最小值。换句话说,这个规则能用在神经网络的学习中。 应用梯度下降规则有很多挑战。我们将在下一章深入讨论。但是现在我想提及一个问题。为了理解问题是什么,我们先回顾(6)中的二次代价函数。注意这个代价函数有着如下的形式【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,也就是说,它是每个样本损失【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数的平均值。事实上,为了计算梯度∇C,我们需要为每个训练样本x单独地计算梯度值【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,然后求平均值,不幸的是,当训练输入过大时会花费很长时间,这样会使学习变得相当缓慢。有种叫做随机梯度下降(SGD)的算法能够用来加速学习过程。想法就是通过随机选取小量输入样本来计算【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 ,进而可以计算∇C。采取少量样本的平均值可以快速地得到梯度∇C,这会加速梯度下降过程,进而加速学习过程。

更准确地说,SGD是随机地选取小量的m个训练数据。我们将选取的这些训练数据标号【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,并把它们称为一个mini-batch。我们选取的m要足够大才能保证【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 的平均值才能接近所有样本的平均值【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数,也就是说,

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

其中,第二个求和是针对整个训练数据集的。交换两边我们可以得到

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

 证实了我们可以通过计算随机选取的mini-batch的梯度来估计整体的梯度。

为了将这种想法更明确地联系到神经网络的学习中来,假设用【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数分别代表权重和偏置。SGD就是随机地选取大小为一个mini-batch的训练数据,然后去训练这些数据,

【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数

这个和就是当前 mini-batch 中每个【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 的梯度值。然后我们再随机选取另一个mini-batch去训练,直到我们用完了所有的训练数据,这就完成了一轮(epoch)迭代训练。这样我们就会重新开始下一轮迭代。值得一提的是,关于调节代价函数和 mini-batch 去更新权重和偏置有很多不同的约定。在(6)式中,我们通过因子【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数来缩放全部的代价函数。人们通常忽略【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数 直接计算单独训练样本损失之和,而不是求平均值。这对我们不能提前知道训练数据集大小的情况下特别有效。这可能发生在有更多的训练数据是实时加入的情况下。同样,mini-batch 的更新规则(20)和(21)有时也会舍弃【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数从概念上这也会有一点区别,因为它等价于重新调节学习速率η。但在对不同工作进行详细比较时,它是值得关注的。

我们能把 SGD 想象成一场*选举:使用小规模的 mini-batch 计算梯度,比使用整个训练集计算梯度容易得多,就如开展一次民意调查比举行一次完整的选举容易得多。举个例子,在 MNIST 中有60,000个测试数据,我们选取 mini-batch 的大小为m=10,这样,计算梯度的过程就加速了6,000倍!当然,这个估计可能并不准确——仍然会存在统计波动——但也没必要准确:我们只关心在某个方向上移动可以减少C,这意味着我们没必要准确去计算梯度的精确值。事实上,SGD 十分有效,广泛应用在神经网络的学习中,它也是本书中展开的大多数学习技术的基础。

练习

  • 梯度下降一个比较极端的版本就是让 mini-batch 的大小为1。这就是说,给定一个输入x,我们通过规则【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数【菜菜的CV进阶之路-神经网络的深入理解-六】通过梯度下降法学习参数更新权重和偏置。当我们选取另一个训练数据时也做同样的处理。其它的训练数据也做相同的处理。这种处理方式就是在线学习(online learning)增量学习(incremental learning)。在在线学习中,神经网络在一个时刻只学习一个训练数据(正如人类的做法)。说出 online learning 相比 mini-batch 为 20 的 SGD 的一个缺点和一个优点。

作为总结,让我们讨论一个可能会让刚刚接触梯度下降的人困惑的问题。在神经网络中,代价函数C是一个关于所有权重和偏置的多元函数,因此在某种意义上来说,就是在一个高维空间定义了一个平面。 有些人可能会那么想:「嗨,我必须要看见其它多出的维度」。他们会开始疑惑:「我不能想象出四维空间,更不用说五维(或者五百万维)」。是不是他们缺少某种只有超级数学家才有的超能力?当然不是。即便是专业的数学家,大多数也不能想象出四维空间的样子。他们会用一些其它的方式来思考。正如我们上面所做的那样,我们可以用代数(而不是几何)来表示ΔC如何变化才能让C减少。善于思考高维的人会在脑中做一些思想实验;我们采用的代数技巧是其中一个方法。这些方法可能不如观察三维那么直观,但我们熟悉这些方法之后会帮助我们思考更高维度。我不想在这里详细展开,如果你感兴趣,你可以读一下这篇关于数学家如何思考高维空间的讨论。我们讲的一些原理可能会有点复杂,但大多数内容还是比较直观的,任何人都能熟练掌握。