convolutional network

文章来自MIT的Deep Learning未出版版本:

@unpublished{Bengio-et-al-2015-Book,
title={Deep Learning},
author={Yoshua Bengio and Ian J. Goodfellow and Aaron Courville},
note={Book in preparation for MIT Press},
url={http://www.iro.umontreal.ca/~bengioy/dlbook},
year={2015}
}

Deep learning Book: Chapter 9. Convolutional Networks

9 Convolutional Networks

Convolutional networks are simply neural networks that use convolution in place of generalmatrix multiplication in at least one of their layers

用线性的简单卷积操作来代替复杂的矩阵相乘,作者认为这是卷积操作被使用的核心思想

9.1 Convolutional Operations 卷积操作

由于以前学过信号与系统,对于卷积操作还是比较熟悉的。这里重新回顾一下卷积操作。
作者拿了宇宙飞船定位的例子引出了卷积操作:
假设现在要对一艘宇宙飞船进行定位(作者是科幻迷么),雷达提供了关于时间的定位函数$x(t)$。现在由于有噪声干扰,我们希望多取几个时间,做平均值作为最终的定位函数$s(t)$。但是我们知道:假设我们要定位时刻t飞船位置,那么x(t)是最重要的依据,x(t-1)和x(t+1)相对x(t)次要一点,而像x(t+8)就更次要了,也就是说离当前时刻t越远的数据对于当前时刻t的定位信息越次要。所以我们引入权重w,比如给w(t)赋最高权重,而w(t-1)就相应低一点。如此我们就重新得到了经过加权处理的定位函数:

$$ s(t) = \int x(a) w(t - a) d_a$$

上面这样的式子就是卷积操作。
为了方便起见,我们把上式写为:

$$ s(t) = (x * w)(t) $$

这里我想说明几点(文章中未提到,但对于卷积不熟悉的人可能会有疑惑):

  1. $积分上下限是从-\infty 到+\infty$
  2. 计算t时刻的位置,把t看成常量,a是变量,对a积分。物理意义表示不同的时间点a的加权和作为t时刻飞船的位置。

把宇宙飞船中的例子拿到神经网络中来,

  • x就是输入
  • w就是kernel
  • 输出就是feature map

在上面的基础上对卷积进行三点扩展:

  1. 通常情况下时间是离散化的,那么卷积的操作相应地就变成了:
    $$s[t] = (x * w) (t) = \sum ^\infty _{a=-\infty} x[a] w[t-a]$$
    注意公式里卷积操作时候上下限是$\infty$,但是我们实际存储中只存储部分值,规定之外的那些x[a]和w[t-a]都是0,卷积的时候为0的项相乘是0。这样把无穷变成了有穷,符合实际操作。

  2. 在Machine Learning中,x和w都是向量,也就是说都是多维的。我们把这些多维的向量叫做tensors

  3. 卷积操作可以使用多个坐标轴。对于二维图像,我们需要使用二维的Kernel函数K:
    $$ s[i, j] = (I ∗K)[i, j] =\sum _m \sum_nI[m, n]K[i − m, j −n] $$
    由于是卷积符合交换律,上式也可以写成:
    $$ s[i, j] = (I ∗K)[i, j] =\sum _m \sum_nI[i - m, j - n]K[m, n] $$
    然而在有些ML库里面,使用了cross-correlation函数,跟卷积很相似:
    $$ s[i, j] = (I ∗K)[i, j] =\sum _m \sum_nI[i + m, j + n]K[m, n] $$
    这里卷积核kernel没有翻转。本书中认为包括cross-correlation函数在内的上面两种方式都是卷积。

下图是Input图像的二坐标轴卷积示意图:
Alt text

9.2 Motivation 动机

卷积的以下三个特点能改进机器学习系统:

  • sparse interactions 稀疏交互
  • parameter sharing 参数共享
  • equivariant representations 等变化表示

此外,卷积对于不同大小的输入都可以进行处理。
下面我们具体来看看这三个特点:

  1. sparse interactions
    现在假设有m个输入和n个输出,如果采用矩阵相乘的操作,那么就需要m _ n个参数,同时算法的时间复杂度有o(m _n),如下图所示:
    Alt text
    该图中输入x有5个,输出s也是5个。s3同时受x1到x5这5个输入变量的影响。
    而在引入了卷积操作之后,我们可以大大地简化存储开销和时间开销。具体地,如果我们限定连接数k(也就是说s3现在只和k个输入有关,而不是与所有的输入都有关),那么我们现在仅需要k_n个参数,而时间复杂度也变成了o(k_n),如下图所示:
    Alt text
    这里取k=3,则s3仅仅和x2、x3、x4这三个输入有关了。
    这里限定k的操作就可以通过引入卷积核来完成,一般来说k比m小好几个数量级别
    而且对于深度网络来说,影响性会通过深度不断累积叠加,我们看下面这个图:
    Alt text
    对于两层的卷积网络来说,h2只受x1,x2,x3的影响,但是g3由于受到h2,h3,h4的影响,导致g3最终受到了x1,x2,x3,x4,x5五个输入的影响。
    从这个例子中我们可以得出:虽然输入可能是稀疏的,但是深度越深,可能导致越不稀疏; 从另一个方面也说明了卷积相对矩阵相乘在深度网络中的优势是随着深度越深,优势越大。

  2. parameter sharing
    其实从9.1节最后那个图就已经很直观地看出卷积的参数共享了。在那幅图里面w,x,y,z这四个kernel核参数被用在每一次卷积操作当中。矩阵相乘需要m * n个权重参数,每个参数都仅仅只用了一次,并没有像卷积那样是重复利用的。下面这个图说明了这个问题(我觉得图画的并不是很有说服力,所以把图改了一下):
    Alt text
    左图是卷积操作,计算每一个s的时候,都用到了三个权值(s1和s5两个边缘情况除外),而且它们共用红色、黑色、蓝色三个权重。
    而右图每一条边对应的权值都不共用。

  3. equivariant representations
    如果说$f(g(x)) = g(f(x))$,那么我们就说$f(x)$关于函数$g$是equivariant的。
    对于卷积操作来讲,如果我们把g看成是输入的一个变换函数,比如平移操作,那么卷积函数f就关于平移函数g是equivariant的。
    具体地,我们首先定义平移操作g:
    $$g(x)[i] = x[i-1]$$
    上面这个函数g相当于把所有输入右移了一个单位。然后我们再对右移后的操作进行卷积。这样得到的结果和先对输入进行卷积,再进行平移操作的结果是一样的。
    这有一个好处,比如我们在卷积网络的第一层做边缘检测的时候,相同的边缘可能会出现在图像中的很多地方。这样只用一个函数就可以在输入中的任何位置(相当于上下或者左右平移)都能检测目标边缘。
    但是注意这里的变换函数g不能是缩放或者旋转操作函数。

9.3 Pooling

一个经典的卷积网络如下:
Alt text
以左图为例子,一个卷积层分为三个部分:

  1. convolution stage,并行的执行卷积操作,产生一系列presynaptic activations
  2. detector stage, 每一个presynaptic activation执行一个nonlinear activation function,例如rectified linear activation function。
  3. pooling stage,使用pooling function修改输出

pooling操作的定义如下:

A pooling function replaces the output of the net at a certain location with asummary statistic of the nearby outputs.
就是用某种方法,用某一个点的值代替该点所在的某个区域。

下图举了一个max pooling的例子:
Alt text
下面一层是detector stage,上面一层是pooling stage,从下面一层到上面一层使用了max pooling。具体地,上层中最左边的那个1选自与下层相连的两个结点的最大值。上层的其他节点也是如此。
注意右图的下层是左图下层右移一个单位的结果。对比左右两幅图我们发现,下层每个节点都不同,上层却有一半的节点是相同的。
从中我们可以得出一个结论:

pooling helps to make the representation become invariant tosmall translations of the input. This means that if we translate the input bya small amount, the values of most of the pooled outputs do not change.
就是说pooling操作可以使得输入那些微小的变化经过pooling操作之后变成相同。

pooling操作的关键思想:

Invariance to local translationcan be a very useful property if we care more about whether some feature is present than exactly where it is.
当我们关注某个特征是否存在而不是它确切的位置的时候,使用pooling操作会很有用。

所以我们在使用pooling的时候必须有一个很强的先验在里面:

我们必须保证网络层学习得到的函数是invariant to small translations的,也就是可以忽略微小变化的。只有当这个假设成立的时候,pooling才可以大大提高网络中统计的效率。

最后,如果我们用1个pixel代替原来的k个pixels, pooling操作使得传给下一层网络的输入减少了k倍,如果后面的网络是做矩阵相乘的全连接层,将会大大提高效率,减少存储空间,如下图所示(相当于下采样):
Alt text
还是使用max pooling,节点数减少了一倍。

9.4 Convolution and Pooling as an Infinitely Strong Prior

为了更加直观的理解卷积和pooling操作,我们把它们看成是具有无限强先验的矩阵相乘操作。
先验Prior可以有强或者弱两种。强先验有着很低的熵,比如具有低方差的高斯分布函数。而一个无限强先验则把某些参数的出现概率设置成为0,也就是说不管实际数据如何,我们都禁止这些参数的出现。
如此一来,我们把卷积网络看成是具有无限强先验的全连接网络。虽然这样不太准确,但是对于我们理解卷积网络有帮助。
通过这样一个类比,我们可以通过直觉容易地得出下面两个结论:

  1. 卷积网络容易欠拟合。因为只有先验假设是正确的情况下,预测才会准确。如果先验不太准确,那么预测就会产生偏差,也就发生了欠拟合。
  2. 在比较两个卷积模型的时候需要在相同的基准下比较。

9.5 Variants of the Basic Convolution Function基本卷积函数的一些变体

在实际使用中,我们的卷积操作跟标准的离散卷积操作略微不同,下面来看看有哪些不同之处:

  1. 当我们提到神经网络中的卷积的时候,我们实际上指的是并行的卷积操作。因为一个卷积核虽然可以提取不同位置的特征,但是提取的都是同一个特征,但是我们希望能够提取不同位置的多个特征。
    另外,输入的x也是向量而不是单一的实数。比如对于rgb图像而言,每一个像素点输入就有三个通道。后面作者写了两个公式作为例子,但是自己没有看懂。
  2. 另外一个重要的特征是输入V可以向两边隐式地扩展0,这样整个输入V向量就会变长。
    我们来看下面这个例子:
    Alt text
    上面这幅图中,我们使用的kernel的大小是6,从下到上每经过一层,单元数目就会少5个。这样就会导致单元数目越来越少。虽然我们可以通过减小kernel来让每次减少的单元数目变少,但是一者kernel不是取越小越好的,二者还是不能从根本上解决问题。
    所以我们才有了zero-padding:
    Alt text
    这幅图中每一层都添加了5个值为0的单元(左边三个,右边两个,用黑色圆圈表示出来),这样一来,保证了每一层单元数目是不变的,没有减少。就解决了上面的那个问题。
    在做zero-padding的时候,我们需要注意三个特殊情况:
  • valid convolution,没有使用zero-padding,也就是第一个图的情况。如果输入大小是m * m, kernel大小是k * k,那么输出大小就是(m - k + 1) * (m - k + 1)。由于最后一层长度是1,所以这种方法的层数有限。

  • same convolution,就是第二幅图片的情况。输出层和输入层的长度是相等的,所以网络的层数在硬件支持的基础上可以无限加深。但是我们需要注意边界的情况,输出层最边界的节点受到输入层节点的影响较少(因为有些是与黑色的zeo-padding连接,卷积结果是0),这使得边界像素不能很好地体现模型的效果。这就促成了第三种网络:

  • full convolution,两边zero-padding,然后每一个节点都用了k次,输出层的大小变成了(m + k - 1) * (m + k - 1),相当于把第一幅图从上往下看。

通常我们的zero-padding基于valid 和 same convolution之间。
后面作者还讲了几种:

  • unshared convolution,结构和卷积网络一样的,但是实际上做的不是卷积,而是使用locally connected layers,这个时候参数就不共享了。
  • tiled convolution,模型相当于convolution layer和locally connected layer的折中,使用了一系列的kernels。

后面就没有看下去了。总之看完这一章之后解决了我对CNN的很多疑惑,虽然没有讲解具体的CNN算法,但是感觉还是非常有用。