卷积神经网络
完整版:https://git.oschina.net/wjiang/Machine-Learning
-
卷积网络简介
卷积网络(leCun,1989),也被称为卷积神经网络或CNN, 它是处理数据的一个特殊的神经网络,它包含一个已知的类网格的拓扑结构。例子包括时间序列,它可以被认为是一个以固定时间间隔采样的1D网格,和图像数据,它被认为是2D像素的网格。卷积网络在实际的应用中已经非常地成功。"卷积神经网络"这个名字表明了网络中采用了一个叫做卷积的数学运算。卷积是一个特殊类型的线性运算。卷积网络是一个简单的神经网络,它至少在3层网络中地一层用卷积代替了一般的矩阵乘法。
这一章,我们首先讲述什么是卷积,接下来我们会解释在一个神经网路中使用卷积背后的动机。然后我们将解释一个名叫"池化(pooling)"的运算,几乎在所有的卷积网络中都会用到它。通常,这个运算在卷积神经网络不符合其他领域例如工程领域和纯数学领域的中关于卷积的定义。我们将描述几个在神经网络实践中广泛应用的卷积函数的变体。我们也将展示卷积可以应用到很多种类型的不同维的数据,然后我们讨论让卷积更加有效的方法。卷积网络作为一个神经科学原理的一个例子脱颖而出并影响着深度学习。我们将讨论这些神经科学原理,最后总结卷积网络在深度学习历史中地角色。这章的一个主题不是介绍如何选择卷积网络架构,这一章的目的是描述卷积网络提供的各种工具,而第11章描述什么情况下选择什么工具的一个通用性的指导。对卷积网络架构的研究进展如此之快以至于一个新的给定基准的最佳架构每周到每几个月就会发布一次,致使在出版物中描述最佳的架构是不可能的。然而,最佳的体系架构始终是由这里所描述的构建块组成的。
-
卷积运算
卷积的一般形式是两个拥有一个实值参数的函数间的一个运算。为了促进卷积的定义,我们先以我们会用到的两个函数做为一个例子开始。
假设我们正在用激光传感器跟踪一个宇宙飞船的位置,我们的激光传感器提供一个单独的输出X(t), 以表示宇宙飞船在t时间的位置。X和t都是实值,例如,我们可能在任意紧急的时刻从激光传感器中得到一个不同的地读入。
现在我们假定我们的激光传感器有一些噪声。为了得到宇宙飞船位置的一个低噪声的估计,我们应该取几次测量的一个平均值。当然,越近的测量则越相关,所以我们希望这个加权平均使得最近的测量更加有分量。我们可以用一个权重函数w(a)来实现,其中a是测量的年代。如果我们每个月应用这个权值平均运算,我们将会得到一个新的函数s提供了宇宙飞船位置平滑的估计。
这个运算叫做卷积,卷积运算典型的以星号表示为:
在我们的例子总,w需要是一个有效的概率密度函数,或者输出不是加权平均值。并且对于所有的负参数,w需要是0,或者展望未来,w的假设值超出我们的能力范围。
这些限制对于我们的例子来说是特别的。一般的,卷积是对那些上面的部分已经定义了的任意函数的定义,并且可能用于其他目的除了执行加权平均值。
卷积网络术语中,卷积的第一个参数(在这个例子中,函数x)通常被称为输入,第二个参数作为核。输出有时候被称为特征映射。
在我们的例子中,激光传感器可以对实例实时的提供测量是不现实。通常,我们在电脑中处理数据,时间是离散的,并且我们的传感器会定期的提供数据。在我们的例子中,可能假设我们的激光传感器每秒提供一次测量更为现实。时间项t只能是整数值。如果我们现在假设x和w在整数的t上定义的,我们就可以定义离散卷积为:
在机器学习应用中,输入通常是一个多维数组并且核通常是适应我们学习算法的一个多维参数数组。参考这些多维数组做为张量,因为每个输入的每个元素和核必须是显形的单独存储的,我们通常假定这些函数在任何地方都为0,但是我们存储这些值得有限的点集。这也就是说在现实中我们可以把有限求和作为一个无限数组元素的求和。
最后,我们经常同时在多个轴上使用卷积,例如,我们用二维图像I作为我们的输入,我们可能总是想要用一个二维的核函数:
卷积是可交换的,也就是说我们可以等价的将上式写成:
通常后一个公式在机器学习库中是比较容易实现的,因为这里m和n在有效值得范围内变化比较小。
卷积的交换律就出现了是因为我们已经将输入相对应的核翻转了,从这个意义上说,随着m的增加,输入的索引增加,而核的索引减小。翻转核函数的唯一原因是为了得到交换律。交换律在写证明的时候很有用,但是它并不是神经网络实现中的一个重要性质。相反,神经网络库实现一个相关函数叫做交叉相关(cross-correlation), 这和卷积一样但是不会翻转核:
很多机器学习库实现了交叉相关,但是却把他叫做卷积。这一节中,我们将遵循这个惯例即把它两都叫做卷积,并且在核翻转是相关的情况下我们是否要翻转核。在机器学习的环境中,学习算法会在合适的位置学习到核的合适的值,所以一个基于卷积并且拥有核翻转特性的算法将会学习一个翻转的核相对于一个由没有翻转的算法学些到的核。在机器学习中单独运用卷积也是非常少见的,相反,卷积是与其他函数同时使用的,并且不管卷积运算是否翻转他的核,这些函数的组合都不会改变。
看图9.1,这个个应用在一个2-D张量卷积(没有核翻转)的例子。
离散卷积可以认为是矩阵的乘法,然而,矩阵有几个元素被约束为等于其他的元素,例如单变量离散卷积,矩阵的每一行被约束为等于上一行平移了一个元素。这就是所谓的托普利兹矩阵,二维中,一个双块循环矩阵对应于卷积,另外这些约束也就是几个元素互相等于对方,卷积通常对应于一个非常稀疏的矩阵(一个元素大多数等于0的矩阵),这是因为核通常小与输入图像,任何以矩阵乘法处理的并且不依赖于特定矩阵结构性质的神经算法都应该运用卷积,而不需要进一步的改变神经网络。典型的卷积神经网络为了有效的处理大量的输入确实运用了进一步的特殊化,但是从理论的角度来说是不是必要的。
图9.1:一个2-D的没有核翻转的卷积。在这种情况下我们限定输出到内核完全位于图像中地位置,在某些情况下叫做"有效"卷积。我们画些盒子来表示左上角的输出张量是怎样运用相对于左上角区域的输入张量的核来形成的。
-
激励
卷积利用三个重要的思想是可以帮助改善一个机器学习系统:稀疏交互、参数共享和等变表示。此外卷积为了处理处理输入变量大小提供了一种方法。我们现在依次来描述这些想法。
传统的神经网络层由包含描述每个输入单元和输出单元之间交互的独立参数的参数矩阵做矩阵乘法。这就意味着每个输出单元都与每个输入单元交互。然而卷积网络,典型的包括稀疏交互(也被称为稀疏连接或稀疏权重),这是通过使核小于输入来完成的。例如,当处理一个图片,输入图片可能有几千个像素,但是我们可以检测小的有意义的特征比如只有几十个或是几百个核的边缘的像素。也就是说我们需要存储更少的参数,这些参数减少模型内存的需求和改善它的统计效率。这也就意味着计算输出需要更少的运算。这些效率上的改善通常是巨大的。如果这里有一个m输入和n输出,于是我们矩阵乘法需要m*n个参数并且实际中算法需要O(m*n)运行时间(每个)。如果我们限制连接到每个输出的数量可能到k,那么稀疏的连接方法只需要k*n个参数和O(k*n)的运行时间。对于很多的实际应用,可能在当k比m小几个数量级的时候在机器学习任务中得到很好的性能。对于稀疏连接的图形演示可以参考图9.2核9.3. 在深度卷积网络中,在更深层次地单元中可能不直接和大量的输入直接交互,例如图9.4显示的。这使得网络能够有效的描述从只描述稀疏交互的简单构建块构造交互的很多变量之间进行的复杂交互。
参数共享指的是对模型中多个函数使用相同的参数,此外传统的神经网络,当计算一个层的输出的时候,权重矩阵的每个元素只用一次,它乘以一个输入并且不会再被访问。作为共享参数的同义词,可以说是一个网络权重绑定(tied weights),因为应用到一个输入的权值被绑定到应用到任何输入的权值。在卷积网络中,核的成员被用在输入的任何位置(除了一些边缘像素,根据设计有关边界的决策)。卷积运算用到的参数共享意味着我们与其为每一个位置学习一个独立的参数集,还不如学习一个参数集。
图9.2 稀疏连接,看下面的部分:我们突出一个输入单元,x3,并且也突出被这个单元影响的输出单元s,(最上面)当s是由一个宽度为3的核函数卷积形成的,只有3个输出受到x的影响。(下面)当s是 由矩阵乘法形成的,连接不再稀疏,所以所有的输出都被x3影响。
图9.3:稀疏连接,看图的上半部分,我们突出一个输出单元,s3,并且突出了影响这个单元的输入单元x。这个些突出的单元被称为感受域(receptive field)s3,。(上半部分)当s是由宽度为3的核函数卷积形成时,只有3个输入影响s3.(下面)当s是由矩阵乘法形成时,连接不再稀疏,所以所有的输入都影响s3.
图9.4:卷积网络中的更深层次单元的感受域(receptive field)比浅层单元的感受域(receptive field)要大。如果网络包含了像条纹卷积(strided convolution)(图9.12)或是池化(pooing)(图9.3)这样的架构特征,这种效应就会增加。意思就是即使在一个卷积网络中直接连接是非常稀疏的,但是更深的层次可以间接的连接所有或者说是大部分输入图像。
图9.5: 参数共享:黑色的箭头表示这些在两个不同模型之间用一个特殊参数的连接。(上半部分)黑色的箭头表示在一个卷积模型中使用一个3元素核函数中心的元素。因为参数共享,这些单参数被用在所有输入位置。(下半部分)单个黑色箭头表示在一个全连接模型中使用权重矩阵中间的元素。这个模型没有参数共享所以参数值被使用一次。
这不影响正向传播的运行-它仍然是O(k*n)-但是它进一步减小k参数模型的存储需求。回想一下k通常比m小几个数量级,因为m和n的大小通常是一样的,与m*n相比k实际上是无关紧要的。因此在内存需求和统计效率方面来说卷积显然比密集的矩阵乘法更有效。有关参数共享是如何工作的图形描述,请参见图9.5.
正如前面两个原则的一个例子,图9.5展示了稀疏连接和参数共享在检测一张图像的边沿可以显著的改善一个线性函数的效率。
在卷积的例子中,参数共享的特殊形式使这个层有一个称为等变性的属性。说一个函数是等变的就是说如果输入改变,输出会以同样的方式改变。特别的,if f(g(x)) = g(f(x)) 一个函数f(x)是等变到另一个函数g。在卷积的情况下,如果我们让g为任何函数来转换输入,例如平移它,那么卷积函数等变到g。例如,让I成为一个给定整数坐标下图像亮度的函数。让g成为一个映射一个图像函数到另一个图像函数的函数,这个 I' = g(I)是一个图像函数I'(x,y) = I(x-1,y)。这个函数把I的每一个像素移到右边,如果我们运用这个转换到函数I,然后运用卷积,结果将和我们运用卷积到I'一样,然后将转换g应用到输出。当处理时间序列数据时,卷积会产生一个时间轴,它显示不同的特征何时出现在输入上。如果我们稍后在输入上移动一个事件,稍后同样的表示会出现在输出中。和图像一样,卷积会创建一个2-D的映射,其中的某些特征会在输入中出现。如果在输出中移动对象,在输出中它的表示将会移动同样的总数。当我们知道应用于多个输入位置时,少量的领域像素的一些函数是有用的,这对我们来说很有用。比如,当处理图像时,卷积网络的第一层检测边沿是很有用的。同样的边沿或多或少的出现在图像中,所以在整个图像中共享参数是很实际的,在某些情况下,我们不能在整个图像中共享参数,比如,如果我们处理的图像被裁减以一个人脸为中心,我们可能想要在不同位置提取不同特征-网络的这部分处理脸上部需要寻找眉毛,而网络的这一部分处理脸下部的时候需要寻找下巴。
卷积不是自然等变到一些其他的转换,比如缩放比例或是图像旋转。其他的机制对于处理这些类型的转换也是非常必要的。
最后,一些数据不能由用固定形状矩阵的矩阵乘法定义的神经网络所处理,卷积却可以对这类数据进行处理,我们将在9.7章节中做进一步的讨论。
-
池化(Pooling)
一个典型的卷积网络层由三个阶段(如图.9.7),在第一个阶段,这一层并行的执行几个卷积产生一个线性激活的子集。在第二阶段,每一个线性激活通过一个非线性激活函数来运行,比如调整线性激活函数,这一级阶段有时候被称为探测器阶段。在第三个阶段,我们 用一个池化函数(pooling function) 来进一步的改变这一层的输出。
一个池化函数将网络的某个位置的输出替换为邻近输出的统计量,例如,最大的池化操作运算报告了最大的输出包含一个矩形邻域。
图9.6:边缘检测的效率。右边的图像是通过提取元素图像中的每个像素并且在左边图像中减去相邻像素的值来形成的。这个图像显示了在输入图像中所有垂直方向上边缘的强度,在目标检测中,这是一个非常有用的操作。两个图像都是280个像素高,输入的图像320个像素宽,而输出图像是319个像素宽。这个变换可以由一个包含两个元素的卷积核来描述并且需要用卷积来计算319*280*3 = 267,960个浮点运算(两个乘数和每个输出像素增加一个)。为了描述一个矩阵乘法的同样的转换需要320*280*319*280,或是80亿个以上,矩阵中的元素,用卷积表示这个转换则会高效40亿倍。简单的矩阵乘法算法执行170亿次浮点运算,从计算方面讲用卷积大概会高效60,000倍。当然,矩阵的大多数元素都是0,如果我们矩阵的非0元素,因此矩阵乘法核卷积需要计算同样数目的浮点型运算。矩阵将仍然需要包含2*319*280 = 178,640个元素。卷积是一种非常有效的描述应用相同变换的方法,在整个输入中对一个小的局部的区域进行转换(图片来源,Paula Goodfellow)。
图9.7:一个典型的卷积神经网络层组件。它包括两个通用术语集来描述这些层次。(左边)在这个术语中,卷积网络被看做是一个小的相对复合层,它的每一层由很多的'stages'。在这个术语中,由核张量核网络层间的一对一的映射。本书中我们一般用的是这种术语。(右边)在这个术语中,卷积网络被看做是一个更大的简单层次;处理的每一步被认为是单独的层。意思就是说不是每一个"层"都有参数。
其他流行的池化函数包括邻域的平均,矩形邻域的L2范数,或者是基于距中心像素距离的加权平均。
在所有情况下,池化有助于使表示变得近似于输入小转化的不变量。转化的不变性意思是说如果我们将输入做一个小量的转换,大多数池化输出值不会改变。参考图9.8 这是如何工作的一个例子。如果我们关心一些特征是否出现更胜于它的确切的位置,本地转换的不变性是一个非常有用的性质。当判断一个图像是否包含一张脸的时候,我们不需要知道眼睛位置的像素级的精度,我们只需要知道脸的左边有一只眼睛并且脸的右边也有一只眼睛。在其他情况下,保存特征位置更为重要。例如,我们想要找到在特定方向上有两条边汇合定义的一个角,我们就需要很好的保存边沿的位置以测试他们是否汇合。
池化可以被认为是增加了一个无限强的先验(prior),即这一层学习的函数必须是对小转化是不变的。当这个假设正确时,就可以极大改善网络统计效率。
在空间区域上的池化产生转化不变性,但是为我们在独立参数化卷积的输出上做池化,特征可以学习到是哪些转换变为不变量。(参考图9.9)
因为池化汇总了整个邻域的响应,它通过报告池化区域间隔为k个像素而不是1个像素的统计汇总,所以可以使用比探测器更少的池化单元。参考9.10的例子。这就改善了网络的计算的效率,因为下一层要处理的输入大概少k倍。当下一层的的参数的数量是它输入大小的函数时候(比如当下一层是全连接并且是基于矩阵乘法的时候),输入大小的减小也可以引起统计效率的改善并且减小存储参数的内存需求。
对于很多任务,池化对于处理大小可变化的(varying)输入来说是必不可少的。比如,如果我们想要将可变大小的图像进行分类,类别层的输入必须是固定大小的,这通常由改变在池化区域间偏移的大小来完成的,所以分类层总是接受同样数量的汇总统计而不管输入大小是多少。例如,网络最后的池化层可能定义输出四组汇总统计,一组用于图像的每个象限(quadrant), 而不考虑图像的大小。
一些理论工作给出了在不同情况下应该使用哪种池化的指导(Boureau et,al,2010)。
图9.8:最大池化引入不变性。(图的上半部)一个卷积层输出的中间部分的视图。下面一行显示了非线性的输出。最上面的一行显示了最大池化的输出,它在池化区域跨了一个像素并且一个池化区域的宽度为3个像素。(最下面)同一个网络在输入已经平移一个像素到右边之后的视图。在最底下一行的每个值已经改变,因为最大的池化单元只对邻域中最大的值敏感,而不是它的确切位置。
图9.9:学习不变性的例子:一个汇集了多个特征的池化单元,这些特征是用单独参数来学习的,它可以学习为对输入转换保持不变。这里我们展示三个学习滤波器的一个子集和一个最大池化单元是怎样学习变成旋转不变的。所有的滤波器想要检测一个手写5,,每个滤波器尝试匹配稍微不同方向的5。当一个5出现在输出的时候,相应的滤波器将匹配它并且检测器单元中引起一个大的激励。不管哪一个池化单元已经被激励,最大的那个池化单元有一个大的激励。这里我们展示网络是怎样处理两个不同的输入,进而导致两个不同的探测器被激活的。对池化单元的影响大致相同。这个原则是由maxout网络(Goodfellow et,al, 2013a)核其他卷积网络所利用。在空间位置上的最大池化是自然不变量的转化,这个多通道的方法只对学习其他转换时必须的。
图9.10: 用降采样(downsampling – 缩减像素采样)的池化,这里我们用一个池宽度为3的最大池和两个池之间的跨度。这减少表示大小的两倍,也下一个层级减小了计算和统计的开销。注意最右边的池化区域由一个较小的,但是如果我们不想要忽略一些探测器单元则必须将其包含在内。
也可以动态的将特征集中在一起,例如,在感兴趣的特征(Boureau et,al,2010)位置运行一个聚类算法。这个方法为每个图片产生出不同的池化区域集。另外一些方法是去学习一个单池化结构,然后应用到所有图片(Jia et al., 2012).
池化可以使得一些类型的使用自顶向下的信息的神经网络结构变得复杂化,比如Boltzmann机器和自编码器。这些问题会在我们在第三部分介绍这些类型的网络时做进一步的讨论。池化在卷积Boltzmann机器将会20.6部分中介绍。在一些可微的网络的需要在池化单元上的反式操作将包含在20.10.6部分中。
一些为分类器用卷积和池化计算卷积网络结构的例子图9.11显示。
限于篇幅到此,持续更新在:https://git.oschina.net/wjiang/Machine-Learning