神经网络与深度学习

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

  1. 神经网络的结构
    神经网络与深度学习
    输入层:最左边的一层,这层中的神经元称为输入神经元。
    隐藏层:中间层称为隐层,因为这层神经元既不是输入也不是输出。“隐藏”实际上只是“不是输入或输出”的意思。
    输出层:最右边的输出层包含输出神经元,在本例中,包含单个输出神经元。
    多层网络有时被称为多层感知机或MLP。
    网络中输入层和输出层的设计通常很简单。例如,假设我们试图确定一个手写图像是否描绘了一个“9”。设计网络的一种自然方法是将图像像素的强度编码到输入神经元中。如果图像是一个64×64灰度图像,那么我们将有4,096=64×64输入神经元,其强度适当地缩放在0和1之间。输出层只有一个神经元,输出值小于0.5表示“输入图像不是9”,大于0.5表示“输入图像是9”。
    在神经网络中,其中一层的输出用作下一层的输入。这种网络称为前馈神经网络。这意味着在网络中没有循环——信息总是向前反馈,而不是向后反馈。如果我们做的有循环,我们最终得到的情况输入σ函数依赖于输出。这很难理解,所以我们不允许这样的循环。
    有循环:递归神经网络。

  2. 一个简单的网络来分类手写数字
    把识别手写数字的问题分成两个子问题:
    1)将包含多个数字的图像分解成一系列独立的图像,每个图像包含一个数字。
    2)对单个数字进行分类
    例如,我们想要打破图像
    神经网络与深度学习
    分成六张独立的图片,
    神经网络与深度学习
    人类可以很容易地解决这个分割问题,但是对于一个计算机程序来说,正确地分割图像是一个挑战。一旦图像被分割,程序就需要对每个单独的数字进行分类。例如,我们想让程序识别上面的第一个数字,
    神经网络与深度学习
    是一个5。
    事实证明,分割问题并不那么难解决,我们重点解决第二个问题,为了识别单个数字,我们将使用一个三层神经网络:
    神经网络与深度学习
    网络的输入层包含编码输入像素值的神经元。正如下一节所讨论的,我们的网络训练数据将包含许多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,将每个神经元视为一个二进制值。4个神经元就足够对答案进行编码,因为24=16比输入数字的10个可能值大。为什么我们的网络要用10个神经元呢?这不是效率低下吗?最终的证明是经验主义的:我们可以尝试这两种网络设计,结果是,对于这个特殊的问题,有10个输出神经元的网络比有4个输出神经元的网络更好地学习识别数字。但这让我们疑惑,为什么使用10个输出神经元效果更好。有没有什么启发能提前告诉我们应该使用10-output编码而不是4-output编码?
    为了理解我们为什么这样做,从基本原理出发,思考一下神经网络在做什么是有帮助的。首先考虑我们使用10个输出神经元的情况。让我们把注意力集中在第一个输出神经元上,这个神经元负责判断数字是不是0。它通过权衡来自隐藏的神经元层的证据来做到这一点。那些隐藏的神经元在做什么?为了方便讨论,假设隐层中的第一个神经元检测到的图像是否如下图所示:
    神经网络与深度学习
    它可以通过对与图像重叠的输入像素进行重加权,而只对其他输入进行轻加权来做到这一点。同理,为了论证,我们假设隐层中的第二、第三、第四神经元检测到是否存在以下图像:
    神经网络与深度学习
    你可能已经猜到了,这四张图片合在一起构成了我们之前看到的数字行中的0图像:
    神经网络与深度学习
    所以如果这四个隐藏的神经元都**了那么我们就可以得出数字是0的结论。当然,这并不是我们可以用来得出图像是0的唯一证据——我们可以通过许多其他方式合法地得到0(比如,通过对上面图像的翻译,或者轻微的扭曲)。但我们可以有把握地说至少在这种情况下我们可以得出输入是0的结论。

  3. 利用梯度下降进行学习
    既然我们已经设计了我们的神经网络,它如何学习识别数字呢?我们首先需要学习的是一个数据集,即所谓的训练数据集。我们将使用MNIST数据集,该数据集包含成千上万张手写数字的扫描图像,以及它们的正确分类。
    神经网络与深度学习
    MNIST的数据分为两部分。第一部分包含60000张图像作为训练数据图像是灰度和28×28像素的大小。MNIST数据集的第二部分是10,000张用作测试数据的图像,也是28×28的灰度图像。
    我们将使用符号x来表示一个训练输入。将每个训练输入x看作一个28×28=784维的向量会很方便。向量中的每个条目表示图像中单个像素的灰度值。我们将用y=y(x)表示相应的期望输出,其中y是一个10维向量。例如,如果一个特定的训练图像x描绘了一个6,那么y(x)=(0,0,0,0,0,0,0,0,1,0,0,0)T是期望的网络输出。注意这里的T是转置运算,把一个行向量变成一个普通的(列)向量。
    我们想要的是一种算法,它能让我们找到权重和偏置,从而使网络的输出近似于所有训练输入的y(x)。为了量化我们在多大程度上实现了这个目标,我们定义了一个成本函数,有时被称为损失或目标函数。我们在本书中使用了成本函数这个术语。
    神经网络与深度学习
    w为网络中所有权值的集合,b为所有偏差,n为训练输入的总数,a是输入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)中的二次函数,这不是一个特别的选择吗?也许如果我们选择一个不同的成本函数我们会得到一个完全不同的最小化权重和偏差的集合?这是一个有效的关注点,稍后我们将重新讨论cost函数,并进行一些修改。然而,方程(6)的二次成本函数对于理解神经网络学习的基础知识非常有用,所以我们暂时只讨论它。
    总而言之,我们==训练神经网络的目标是找到使二次成本函数C(w,b)最小化的权值和偏差。==这是一个很好的问题,但是它有很多分散注意力的结构就像现在提出的——将w和b解释为权重和偏置,σ函数潜伏在背景、网络体系结构的选择,MNIST等等。结果是,我们可以通过忽略大部分的结构来理解大量的内容,而只关注最小化方面。现在我们要忘记所有关于成本函数的具体形式,与神经网络的联系,等等。相反,我们假设我们只是得到了一个有很多变量的函数我们想要最小化这个函数。我们要开发一种叫做梯度下降的技术,它可以用来解决这样的最小化问题。然后我们会回到我们想要最小化的神经网络的特定函数。
    假设我们要最小化某个函数C(v)它可以是任意多变量v=v1,v2,…v=v1,v2,…. 的实值函数,注意,我已经用v代替了w和b的符号来强调它可以是任何函数——我们不再专门考虑神经网络的情况。为了最小化C(v)我们可以把C想象成一个只有两个变量的函数,我们称它为v1和v2:
    神经网络与深度学习
    我们要做的是找出C在哪里达到全局最小值。当然,对于上面所画的函数,我们可以仔细观察它的图像并找出它的最小值。在这个意义上,我可能展示了一个稍微过于简单的函数!一个通用的函数C,可能是一个包含很多变量的复杂函数,通常不可能仅仅通过观察图形来找出最小值。
    解决这个问题的一种方法是用微积分来分析求最小值。我们可以计算导数然后试着用它们找出C是极值的地方。如果幸运的话,当C是一个或几个变量的函数时,这种方法可能会奏效。但是当我们有更多的变量时,它会变成一个噩梦。 对于神经网络,我们通常需要更多的变量——最大的神经网络具有成本函数,它以极其复杂的方式依赖于数十亿的权重和偏差。用微积分来最小化是行不通的!
    (在断言我们将通过把C想象成只有两个变量的函数来深入了解它之后,我在两段话中回过头来两次说:“嘿,但是如果它是一个不止两个变量的函数呢?”很抱歉。请相信我,把C想象成两个变量的函数确实很有帮助。有时这幅图会崩溃,最后两段就是关于这种崩溃的。对数学的良好思考通常包括处理多个直觉图像,学习何时使用每个图像合适,何时不合适。)
    好吧,微积分不管用。幸运的是,这里有一个很好的类比,它说明了一种非常有效的算法。我们首先把我们的功能想象成一个山谷。如果你对上面的情节稍微有点斜视,那应该不会太难。我们想象一个球滚下山谷的斜坡。我们的日常经验告诉我们,这个球最终会滚到谷底。也许我们可以用这个方法来求函数的最小值?我们会随机选择一个(假想的)球的起点,然后模拟球滚到山谷底部时的运动。我们可以简单地通过计算C的导数(或许还有一些二阶导数)来进行这个模拟——这些导数将告诉我们我们需要知道的关于山谷的局部“形状”的一切,因此我们的球应该如何滚动。
    根据我刚写的,你可能会认为我们要写出球的牛顿运动方程,考虑摩擦力和重力的影响,等等。实际上,我们不会把滚动球的类比太当真——我们是在设计一个算法来最小化C,而不是开发一个精确的物理定律模拟!俯视是为了激发我们的想象力,而不是限制我们的思维。因此而不是进入所有混乱的物理细节,让我们简单地问自己:如果我们被宣布上帝一天,并可能构成自己的物理定律,决定如何滚球,什么法律或运动定律我们可以选择,让球总是滚山谷的底部?
    为了让这个问题更精确,让我们想想会发生什么,当我们在v1的方向移动球很小的Δv1 ,在v2方向移动很小的Δv2,微积分告诉我们C的变化如下:
    神经网络与深度学习
    我们要找到一种方法选择Δv1和Δv2使ΔC为负;即。我们会选择它们,这样球就会滚进山谷。为了找出如何让这种选择有助于定义Δv成为向量v的改变向量,Δv≡(Δv1,Δv2) T,这里T是转置运算,把行向量变成列向量。我们还将C的梯度定义为偏导向量,(∂C/∂v1,∂C/∂v2)T。我们通过∇C表示梯度向量,即:
    神经网络与深度学习
    稍后我们将改写改变ΔC,用Δv和梯度∇C来表示。在讲这个之前,我想澄清一些有时会让人对梯度感到困惑的东西。当会议首次∇C符号,人们有时不知道他们应该如何看待∇符号。那么,确切地说,∇意味着什么?事实上,这是完全可以把∇C作为一个数学对象——上面定义的向量,它是用两个符号。在这个角度看,∇只是一块符号摇旗呐喊,告诉你“嘿,∇C是一个梯度向量”。有更先进的观点,∇可以被视为一个独立的数学实体本身(例如,作为微分算子),但是我们不需要这样的观点。
    这些定义的表达式(7)ΔC可以写成
    神经网络与深度学习
    这个方程可以解释为什么∇C称为梯度向量:∇C关联 从v的变化到C的变化,就像我们期望的梯度要做的一样。但真正令人兴奋的是这个等式让我们看到如何选择Δv使ΔC为负。特别地,假设我们选择
    神经网络与深度学习
    η是一个小,正的参数(即学习速率)。方程(9)告诉我们,ΔC≈−η∇C⋅∇C =−η∥∇C∥2。因为∥∇C∥2≥0,这可以保证ΔC≤0,即。如果我们按照式(10)中的方法改变v,则C始终会减小,而不会增大。(当然,在方程(9)近似的范围内)。这正是我们想要的!所以我们用方程(10)来定义梯度下降算法中球的“运动定律”。也就是说,我们将使用方程(10)为Δv计算一个值,然后将球的位置v更新为:
    神经网络与深度学习
    然后我们将再次使用这个更新规则,以进行另一个操作。如果我们继续这样做,一遍又一遍,我们将继续减少C,直到——我们希望——我们达到一个全局的最小值。
    总结,梯度下降算法的工作方式是反复计算梯度∇C,然后向相反的方向移动,“跌倒”的斜率山谷。我们可以这样想象:
    神经网络与深度学习
    请注意,使用这个规则,梯度下降并不能重现真实的物理运动。在现实生活中,球有动量,这种动量可以使它滚过斜坡,甚至(暂时)滚上山坡。只有在摩擦力的作用下,球才能保证滚进山谷。相比之下,我们的规则选择Δv只是说“下降,现在”。这仍然是求最小值的一个很好的规则!
    梯度下降法正常工作,我们需要选择学习率η是足够小的,方程(9)是一个很好的近似。如果我们不,我们可能最终ΔC > 0,这显然不是好!与此同时,我们不希望η太小,因为这将使Δv微小变化,因此梯度下降算法将非常缓慢。
    即使C是一个包含更多变量的函数,一切都是一样的。
    把梯度下降更新规则写成分量的形式:
    神经网络与深度学习
    当训练输入的数量非常大时,这可能会花费很长时间,因此学习就会很慢——一种叫做随机梯度下降的思想可以用来加速学习。
    神经网络与深度学习
    神经网络与深度学习
    证实了仅对随机选择的小批样本进行梯度计算,就可以估计总体梯度。
    为了明确地将其与神经网络中的学习联系起来,假设wk和bl表示神经网络中的权值和偏差。然后随机梯度下降法通过随机选择一小批训练输入,
    神经网络与深度学习
    其中的总和是在当前的小批量中的所有的训练例子Xj。然后,我们随机挑选另一批mini-batch,并训练他们。以此类推,直到我们耗尽了所有的训练投入,也就是说完成了一个训练的新纪元。那时我们将开始一个新的训练时期。