在应用计算机视觉时要面临一个挑战,就是数据的输入可能会非常大。举个例子,在过去的课程中,一般操作的都是64×64的小图片,实际上,它的数据量是64×64×3,因为每张图片都有3个颜色通道。如果计算一下的话,可得知数据量为12288,所以我们的特征向量 x 维度为12288。这其实还好,因为64×64真的是很小的一张图片。如果你要操作更大的图片,比如一张1000×1000的图片,它足有1兆那么大,但是特征向量的维度达到了1000×1000×3,因为有3个RGB通道,所以数字将会是300万。
如果第一隐藏层中有1000个隐藏单元,所有的权值组成矩阵 W [ 1 ] W^{[1]} W[1], W [ 1 ] W^{[1]} W[1]将会有30亿个参数,这是个非常巨大的数字。在参数如此大量的情况下,难以获得足够的数据来防止神经网络发生过拟合和竞争需求,要处理包含30亿参数的神经网络,巨大的内存需求让人不太能接受。
但对于计算机视觉应用来说,你肯定不想它只处理小图片,你希望它同时也要能处理大图。为此,你需要进行卷积计算,它是卷积神经网络中非常重要的一块。下面将用边缘检测的例子来说明卷积的含义。
卷积运算是卷积神经网络最基本的组成部分,使用边缘检测作为入门样例。下面介绍卷积是如何进行运算的。
如上所示的图片,如果让电脑去搞清楚这张照片里有什么物体,你可能做的第一件事是检测图片中的垂直边缘。比如说,在这张图片中的栏杆就对应垂直线,与此同时,这些行人的轮廓线某种程度上也是垂线,这些线是垂直边缘检测器的输出。同样,你可能也想检测水平边缘,比如说这些栏杆就是很明显的水平线,它们也能被检测到。那么如何在图像中检测这些边缘?
例如,上图左侧是一个6×6的灰度图像。因为是灰度图像,所以它是6×6×1的矩阵,而不是6×6×3的,因为没有RGB三通道。为了检测图像中的垂直边缘,你可以构造一个3×3矩阵。在卷积神经网络的术语中,它被称为过滤器(有时候也被称为核)。我要构造一个3×3的过滤器, [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix} 1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1\\ \end{bmatrix} 111000−1−1−1 。对这个6×6的图像进行卷积运算,卷积运算用 " * " 来表示,用3×3的过滤器对其进行卷积。
这个卷积运算的输出将会是一个4×4的矩阵,你可以将它看成一个4×4的图像。下面来说明是如何计算得到这个4×4矩阵的。为了计算第一个元素,在4×4左上角的那个元素,使用3×3的过滤器,将其覆盖在输入图像,如下图所示。然后进行元素乘法(element-wise products)运算 [ 3 ∗ 1 0 ∗ 0 1 ∗ ( − 1 ) 1 ∗ 1 5 ∗ 0 8 ∗ ( − 1 ) 2 ∗ 1 7 ∗ 0 7 ∗ ( − 1 ) ] \begin{bmatrix} 3*1 & 0*0 & 1*(-1)\\ 1*1 & 5*0 & 8*(-1)\\ 2*1 & 7*0 & 7*(-1)\\ \end{bmatrix} 3∗11∗12∗10∗05∗07∗01∗(−1)8∗(−1)7∗(−1) = [ 3 0 − 1 1 0 − 8 2 0 − 7 ] \begin{bmatrix} 3 & 0 & -1\\ 1 & 0 & -8\\ 2 & 0 & -7\\ \end{bmatrix} 312000−1−8−7 ,然后将该矩阵每个元素相加得到最左上角的元素,即 3 + 1 + 2 + 0 + 0 + 0 + ( − 1 ) + ( − 8 ) + ( − 2 ) = − 5 3+1+2+0+0+0+(−1)+(−8)+(−2)=−5 3+1+2+0+0+0+(−1)+(−8)+(−2)=−5。
接下来,为了弄明白第二个元素是什么,你要把蓝色的方块,向右移动一步:
继续做同样的元素乘法,然后加起来,所以是 0 ∗ 1 + 5 ∗ 1 + 7 ∗ 1 + 1 ∗ 0 + 8 ∗ 0 + 2 ∗ 0 + 2 ∗ ( − 1 ) + 9 ∗ ( − 1 ) + 5 ∗ ( − 1 ) = − 4 0 ∗ 1 + 5 ∗ 1 + 7 ∗ 1 + 1 ∗ 0 + 8 ∗ 0 + 2 ∗ 0 + 2 ∗ ( − 1 ) + 9 ∗ ( − 1 ) + 5 ∗ ( − 1 ) = − 4 0∗1+5∗1+7∗1+1∗0+8∗0+2∗0+2∗(−1)+9∗(−1)+5∗(−1)=−4
以此类推,蓝色方块移动到最右边时,往下移动一格后继续从最左边开始。这样计算完矩阵中的其他元素。知道计算完底部右下角的3×3区域。
因此6×6矩阵和3×3矩阵进行卷积运算得到4×4矩阵。这些图片和过滤器是不同维度的矩阵,但左边矩阵容易被理解为一张图片,中间的这个被理解为过滤器,右边的图片我们可以理解为另一张图片。
为什么这个可以做垂直边缘检测呢?让我们来看另外一个例子。这是一个简单的6×6图像,左边的一半是10,右边一般是0。如果你把它当成一个图片,左边那部分看起来是白色的,像素值10是比较亮的像素值,右边像素值比较暗,使用灰色来表示0。图片里,有一个特别明显的垂直边缘在图像中间,这条垂直线是从黑到白的过渡线,或者从白色到深色。
当你用一个3×3过滤器进行卷积运算的时候,这个3×3的过滤器可视化为矩阵下方的样子,在左边有明亮的像素,然后有一个过渡,0在中间,然后右边是深色的。卷积运算后,你得到的是右边的矩阵。
如果把最右边的矩阵当成图像,它是在中间有段亮一点的区域,对应到这个6×6图像中间的垂直边缘,这里的维数似乎有点不正确,检测到的边缘太粗了。因为在这个例子中,图片太小了。如果你用一个1000×1000的图像,而不是6×6的图片,你会发现其会很好地检测出图像中的垂直边缘。
从垂直边缘检测中可以得到的启发是,因为我们使用3×3的矩阵(过滤器),所以垂直边缘是一个3×3的区域,左边是明亮的像素,中间的并不需要考虑,右边是深色像素。在这个6×6图像的中间部分,明亮的像素在左边,深色的像素在右边,就被视为一个垂直边缘,卷积运算提供了一个方便的方法来发现图像中的垂直边缘。
如上图所示,和之前的图相比颜色被翻转了,变成了左边比较暗,而右边比较亮。如果你用它与相同的过滤器进行卷积,最后得到的图中间会是-30,而不是30。如果你将矩阵转换为图片,就会是该矩阵下面图片的样子。现在中间的过渡部分被翻转了,之前的30翻转成了-30,表明是由暗向亮过渡,而不是由亮向暗过渡。
上图中右边这个过滤器,它能让你检测出水平的边缘。提醒一下,一个垂直边缘过滤器是一个3×3的区域,它的左边相对较亮,而右边相对较暗。相似的,右边这个水平边缘过滤器也是一个3×3的区域,它的上边相对较亮,而下方相对较暗。
总而言之,通过使用不同的过滤器,你可以找出垂直的或是水平的边缘。但事实上,对于这个3×3的过滤器来说,我们只使用了其中的一种数字组合。还可以使用如下图所示的其他数字组合。
随着深度学习的发展,我们学习的其中一件事就是当你真正想去检测出复杂图像的边缘,你不一定要去使用那些研究者们所选择的这九个数字。可以把这矩阵中的9个数字当成9个参数,并且在之后使用反向传播算法,其目标就是去理解这9个参数。这种将这9个数字当成参数的思想,已经成为计算机视觉中最为有效的思想之一。
为了构建深度神经网络,你需要学会使用的一个基本的卷积操作就是padding。
如果我们有一个 n ∗ n n*n n∗n 的图像,用 f ∗ f f*f f∗f 的过滤器做卷积,那么输出的维度就是 ( n − f + 1 ) ∗ ( n − f + 1 ) (n-f+1)*(n-f+1) (n−f+1)∗(n−f+1)。在上面的例子就是 6 − 2 + 1 = 4 6-2+1=4 6−2+1=4,因此得到了一个 4 × 4 4×4 4×4的输出。
这样的话会有两个缺点,第一个缺点是每次做卷积操作,你的图像就会缩小,从6×6缩小到4×4,你可能做了几次之后,你的图像就会变得很小了,可能会缩小到只有1×1的大小。
第二个缺点是,如果你注意角落边缘的像素,例如最左上角的像素,只被一个输出所触碰或者使用,因为它位于这个3×3的区域的一角。但如果是在中间的像素点,就会有许多3×3的区域与之重叠。所以那些在角落或者边缘区域的像素点在输出中采用较少,意味着你丢掉了图像边缘位置的许多信息。
为了解决这些问题,你可以在卷积操作之前填充这幅图像。你可以沿着图像边缘再填充一层像素,那么6×6的图像就被你填充成了一个8×8的图像。如果你用3×3的图像对这个8×8的图像卷积,你得到的输出就不是4×4的,而是6×6的图像,你就得到了一个尺寸和原始图像6×6的图像。习惯上,你可以用0去填充, p = 1 p = 1 p=1 ,输出也就变成了 ( n + 2 p − f + 1 ) ∗ ( n + 2 p − f + 1 ) (n+2p-f+1)*(n+2p-f+1) (n+2p−f+1)∗(n+2p−f+1)。这样,角落和图像边缘的信息发挥的作用较小的这一缺点就被削弱了。
如果你想的话,也可以填充两个像素点,。实际上你还可以填充更多像素。至于选择填充多少像素,通常有两个选择,分别叫做Valid卷积和Same卷积。
Valid卷积意味着不填充。
Same卷积,意味你填充后,你的输出大小和输入大小是一样的。如果你有一个 n ∗ n n*n n∗n 的图像,用 p p p 个像素填充边缘,输出的大小就是 ( n + 2 p − f + 1 ) ∗ ( n + 2 p − f + 1 ) (n+2p-f+1)*(n+2p-f+1) (n+2p−f+1)∗(n+2p−f+1)。当 f f f 是一个奇数的时候,只要选择相应的填充尺寸,你就能确保得到和输入相同尺寸的输出。
卷积中的步长是另一个构建卷积神经网络的基本操作。
举个例子,如果你想用3×3的过滤器卷积这个7×7的图像,和之前不同的是,我们把步幅设置成了2。还和之前一样取左上方的3×3区域的元素的乘积,再加起来,最后结果为91。
现在移动的步长是2,我们让过滤器跳过2个步长,注意一下左上角,这个点移动到其后两格的点,跳过了一个位置。然后你还是将每个元素相乘并求和,你将会得到的结果是100。
之后以此类推,将蓝色框移动两个步长,你将会得到83。当你移动到下一行的时候,也是使用步长2而不是步长1,所以我们将蓝色框移动到这里:
然后继续移动两个步长,会得到91,127,最后一行分别是44,72,74。
在这个例子中,我们用 3 × 3 3×3 3×3 的矩阵卷积一个 7 × 7 7×7 7×7 的矩阵,得到一个 3 × 3 3×3 3×3 的输出。输入和输出的维度是由下面的公式决定的。如果你用一个 f ∗ f f ∗ f f∗f 的过滤器卷积一个 n ∗ n n ∗ n n∗n 的图像,你的padding为 p p p ,步幅为 s s s ,输出于是变为: ( n + 2 p − f s + 1 ) ∗ ( n + 2 p − f s + 1 ) (\frac{n+2p-f}{s}+1)*(\frac{n+2p-f}{s}+1) (sn+2p−f+1)∗(sn+2p−f+1) 在我们的这个例子里, n = 7 , p = 0 , f = 3 , 7 + 0 − 3 2 + 1 = 3 n=7,p=0,f=3,\frac{7+0-3}{2}+1=3 n=7,p=0,f=3,27+0−3+1=3,即 3×3 的输出。
如果商不是一个整数怎么办?在这种情况下,我们向下取整。 ⌊ ⌋ ⌊ ⌋ ⌊⌋ 这是向下取整的符号,这也叫做对 z z z 进行地板除 (floor),这意味着 z z z 向下取整到最近的整数。这个原则实现的方式是,你只在蓝框完全包括在图像或填充完的图像内部时,才对它进行运算。如果有任意一个蓝框移动到了外面,那你就不要进行相乘操作。
我们已经知道如何对二维图像做卷积了,现在看看如何执行三维立体上的卷积。
假如说你不仅想检测灰度图像的特征,也想检测RGB彩色图像的特征。彩色图像如果是6×6×3,这里的3指的是三个颜色通道,你可以把它想象成三个6×6图像的堆叠。为了检测图像的边缘或者其他的特征,不是把它跟原来的3×3的过滤器做卷积,而是跟一个三维的过滤器,它的维度是3×3×3,这样这个过滤器也有三层,对应红绿、蓝三个通道。
对于6×6×3的图像,这里的第一个6代表图像高度,第二个6代表宽度,这个3代表通道(也可以叫做深度)的数目。同样你的过滤器也有一个高,宽和通道数,并且图像的通道数必须和过滤器的通道数相等。图像和过滤器卷积之后,输出会是一个4×4的图像,注意是4×4×1,最后一个数不是3了。
我们研究下这背后的细节。为了简化这个3×3×3过滤器的图像,我们把它画成一个三维的立方体。为了计算这个卷积操作的输出,你要做的就是把这个3×3×3的过滤器先放到最左上角的位置,这个3×3×3的过滤器有27个数。依次取这27个数,然后乘以相应的红绿蓝通道中的数字,然后把这些数都加起来,就得到了输出的第一个数字。如果要计算下一个输出,你把这个立方体滑动一个单位,再与这27个数相乘,把它们都加起来,就得到了下一个输出,以此类推。
那么,这个能干什么呢?举个例子,过滤器是3×3×3的,如果你想检测图像红色通道的边缘,那么你可以将第一个过滤器设为 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix} 1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1 \end{bmatrix} 111000−1−1−1 ,而绿色和蓝色通道全为0,如果你把这三个堆叠在一起形成一个3×3×3的过滤器,那么这就是一个检测垂直边界的过滤器,但只对红色通道有用。或者如果你不关心垂直边界在哪个颜色通道里,那么你可以将三个通道的过滤器都设置为 [ 1 0 − 1 1 0 − 1 1 0 − 1 ] \begin{bmatrix} 1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1 \end{bmatrix} 111000−1−1−1 ,这样就得到一个 3×3×3 的边界检测器,用来检测任意颜色通道里的边界。
如果我们不仅仅想要检测垂直边缘怎么办?如果我们同时检测垂直边缘和水平边缘,还有45°倾斜的边缘怎么做?换句话说,如果你想同时用多个过滤器怎么办?
图像与第一个过滤器卷积,可以得到第一个4×4的输出,然后卷积第二个过滤器,得到一个不同的4×4的输出。我们做完卷积,然后把这两个4×4的输出,取第一个把它放到前面,然后取第二个过滤器输出放到后面。把这两个输出堆叠在一起,这样你就都得到了一个4×4×2的输出立方体。
这个对立方体卷积的概念真的很有用,你现在可以用它的一小部分直接在三个通道的RGB图像上进行操作。更重要的是,你可以检测两个特征,比如垂直和水平边缘或者10个或者128个或者几百个不同的特征,并且输出的通道数会等于你要检测的特征数。
总结一下维度。如果你用一个 f ∗ f ∗ n c f ∗ f * n_c f∗f∗nc 的过滤器卷积一个 n ∗ n ∗ n c n ∗ n * n_c n∗n∗nc 的图像,输出于是变为: ( n − f + 1 ) ∗ ( n − f + 1 ) ) ∗ n c ′ (n-f+1)*(n-f+1))*n_{c^{'}} (n−f+1)∗(n−f+1))∗nc′,这里的 n c ′ n_{c^{'}} nc′ 是下一层的通道数,也就是你用的过滤器的个数。
继续沿用上面的示例,通过两个过滤器卷积处理一个三维图像,并输出两个不同的4×4矩阵。各自形成一个卷积神经网络层,然后增加偏差(是一个实数),通过Python的广播机制给这16个元素都加上同一偏差。然后应用非线性函数(比如非线性激活函数ReLU),输出结果是一个4×4矩阵。得到了两个矩阵后堆叠起来,最终得到一个4×4×2的矩阵。我们通过计算,从6×6×3的输入推导出一个4×4×2矩阵,它是卷积神经网络的一层,把它映射到标准神经网络中四个卷积层中的某一层或者一个非卷积神经网络中。
前向传播中的一个操作是 z [ 1 ] = W [ 1 ] a [ 0 ] + b [ 1 ] z^{[1]}=W^{[1]}a^{[0]}+b^{[1]} z[1]=W[1]a[0]+b[1],其中 a [ 0 ] = x a^{[0]}=x a[0]=x,执行非线性函数得到 a [ 1 ] a^{[1]} a[1],即 a [ 1 ] = g ( z [ 1 ] ) a^{[1]}=g(z^{[1]}) a[1]=g(z[1])。在卷积操作中,输入是 a [ 0 ] a^{[0]} a[0],也就是 x x x,过滤器用变量 W [ 1 ] W^{[1]} W[1]表示。在卷积过程中,对过滤器的27个数进行操作,取这些数做乘法,这实际执行了一个线性函数,得到一个4×4的矩阵,卷积操作的作用就类似于 W [ 1 ] a [ 0 ] W^{[1]}a^{[0]} W[1]a[0],然后再加上偏差。最后应用激活函数ReLu,得到4×4×2矩阵,得到 a [ 1 ] a^{[1]} a[1] 成为神经网络的下一层,也就是激活层。这就是 a [ 0 ] a^{[0]} a[0]到 a [ 1 ] a^{[1]} a[1]的演变过程。
示例中我们有两个过滤器,也就是有两个特征,因此我们才最终得到一个4×4×2的输出。但如果我们用了10个过滤器,将它们堆叠在一起,会形成一个4×4×10的输出图像,也就是 a [ 1 ] a^{[1]} a[1]。
下面我们总结一下用于描述卷积层的各种标记。
f [ l ] f^{[l]} f[l] 表示过滤器大小,上标 [ l ] [l] [l]表示第 l l l层。 p [ l ] p^{[l]} p[l] 用来标记padding的数量。 s [ l ] s^{[l]} s[l]标记步幅。
此例中,所用图片的高度和宽度都一样,但它们也有可能不同,分别用上下标 H 和 W 来标记。在第 l l l层,作为输入,图片大小就是 n H [ l − 1 ] ∗ n W [ l − 1 ] ∗ n c [ l − 1 ] n_H^{[l-1]}*n_W^{[l-1]}*n_c^{[l-1]} nH[l−1]∗nW[l−1]∗nc[l−1],因为 l l l层的输入就是上一层的输出,即上一层的激活值,因此上标要用 [ l − 1 ] [l-1] [l−1] 。神经网络这一层中会有输出,输出图像的大小为 n H [ l ] ∗ n W [ l ] ∗ n c [ l ] n_H^{[l]}*n_W^{[l]}*n_c^{[l]} nH[l]∗nW[l]∗nc[l]。
l l l层输出图像的高度 n H [ l − 1 ] = ⌊ n H [ l − 1 ] + 2 p [ l ] − f [ l ] s [ l ] + 1 ⌋ n_H^{[l-1]}=⌊\frac{n_H^{[l-1]}+2p^{[l]}-f^{[l]}}{s^{[l]}}+1⌋ nH[l−1]=⌊s[l]nH[l−1]+2p[l]−f[l]+1⌋(注意向下取整),同理用W替换参数H,可以得到图像的宽度。
过滤器中通道的数量必须与输入中通道的数量一致,输出图像中的通道数量就是神经网络中这一层所使用的过滤器的数量。因此,输出通道数量就是输入通道数量,所以过滤器维度等于 f [ l ] ∗ f [ l ] ∗ n c [ l − 1 ] f^{[l]}*f^{[l]}*n_c^{[l-1]} f[l]∗f[l]∗nc[l−1]。
除了卷积层,卷积网络也经常使用池化层来缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性。
假如输入是一个4×4矩阵,用到的池化类型是最大池化(max pooling)。执行最大池化的树池是一个2×2矩阵。执行过程非常简单,把4×4的输入拆分成不同的区域,我把这个区域用不同颜色来标记。对于2×2的输出,输出的每个元素都是其对应颜色区域中的最大元素值。
为了计算出右侧这4个元素值,我们需要对输入矩阵的2×2区域做最大值运算。这就像是应用了一个规模为2的过滤器,因为我们选用的是2×2区域,步幅是2,这些就是最大池化的超参数。
你可以把这个4×4区域看作是某些特征的集合,也就是神经网络中某一层的非激活值集合。数字大意味着可能探测到了某些特定的特征,左上象限具有的特征可能是一个垂直边缘或者其他特征,显然左上象限中存在这个特征。然而,右上象限并不存在这个特征。最大化操作的功能就是只要在任何一个象限内提取到某个特征,它都会保留在最大化的池化输出里。所以最大化运算的实际作用就是,如果在过滤器中提取到某个特征,那么保留其最大值。如果没有提取到这个特征,那么其中的最大值也还是很小,这就是最大池化的直观理解。
池化层其中一个有意思的特点就是,它有一组超参数,但并没有参数需要学习。实际上,梯度下降没有什么可学的,一旦确定了 f 和 s ,它就是一个固定运算,梯度下降无需改变任何值。
另外还有一种类型的池化,平均池化,它不太常用。这种运算顾名思义,选取的不是每个过滤器的最大值,而是平均值。目前来说,最大池化比平均池化更常用。
下面构建一个全卷积神经网络。
假设,有一张大小为32×32×3的输入图片,这是一张RGB模式的图片,你想做手写体数字识别。32×32×3的RGB图片中含有某个数字,比如7,你想识别它是从0-9这10个数字中的哪一个,我们构建一个神经网络来实现这个功能。
输入是32×32×3的矩阵,假设第一层使用过滤器大小为5×5,步幅是1,padding是0,过滤器个数为6,那么输出为28×28×6。将这层标记为CONV1,它用了6个过滤器,增加了偏差,应用了非线性函数,可能是ReLU非线性函数,最后输出CONV1的结果。
然后构建一个池化层,这里选择用最大池化,参数 f = 2 , s = 2 , p = 0 f = 2 , s = 2,p=0 f=2,s=2,p=0 ,构建池化层,这层的高度和宽度会减少一半,因此,28×28变成了14×14,通道数量保持不变,所以最终输出为14×14×6,将该输出标记为POOL1。
人们发现在卷积神经网络文献中,卷积有两种分类,这与所谓层的划分存在一致性。一类卷积是一个卷积层和一个池化层一起作为一层,这就是神经网络的Layer1。另一类卷积是把卷积层作为一层,而池化层单独作为一层。人们在计算神经网络有多少层时,通常只统计具有权重和参数的层。因为池化层没有权重和参数,只有一些超参数。这里,我们把CONV1和POOL1共同作为一个卷积,并标记为Layer1。
我们对Layer1再构建一个卷积层,过滤器为5×5,即 f = 5 , s = 1 , p = 0 f = 5 ,s=1,p=0 f=5,s=1,p=0,过滤器16个,所以CONV2输出为10×10×16。这是CONV2层。然后做最大池化,超参 f = 2 , s = 2 f=2,s=2 f=2,s=2 ,最后输出为5×5×16,标记为POOL2,这就是神经网络的第二个卷积层,即Layer2。
5×5×16矩阵包含400个元素,现在将POOL2平整化为一个大小为400的一维向量。我们可以把平整化结果想象成这样的一个神经元集合,然后利用这400个单元构建下一层。下一层含有120个单元,这就是我们第一个全连接层,标记为FC3。这400个单元与120个单元的每一项相连接,这就是全连接层。它很像我们在第一和第二门课中讲过的单神经网络层,这是一个标准的神经网络。它的权重矩阵为 W [ 3 ] W^{[3]} W[3],维度为120×400,还有一个偏差参数。最后输出120个维度,因为有120个输出。
然后我们对这个120个单元再添加一个全连接层,这层更小,假设它含有84个单元,标记为FC4。
最后,用这84个单元填充一个softmax单元。如果我们想通过手写数字识别来识别手写0-9这10个数字,这个softmax就会有10个输出。
神经网络的基本构造模块我们已经讲完了,一个卷积神经网络包括卷积层、池化层和全连接层。
和只用全连接层相比,卷积层的两个主要优势在于参数共享和稀疏连接。
假设有一张32×32×3维度的图片,假设用了6个大小为5×5的过滤器,输出维度为28×28×6。32×32×3=3072,28×28×6=4704。我们构建一个神经网络,其中一层含有3072个单元,下一层含有4074个单元,两层中的每个神经元彼此相连,然后计算权重矩阵,它等于4074×3072≈1400万,所以要训练的参数很多。虽然以现在的技术,我们可以用1400多万个参数来训练网络,因为这张32×32×3的图片非常小,训练这么多参数没有问题。如果这是一张1000×1000的图片,权重矩阵会变得非常大。我们看看这个卷积层的参数数量,每个过滤器都是5×5,一个过滤器有25个参数,再加上偏差参数,那么每个过滤器就有26个参数,一共有6个过滤器,所以参数共计156个,参数数量还是很少。
卷积网络映射这么少参数有两个原因:
一是参数共享。观察发现,特征检测如垂直边缘检测如果适用于图片的某个区域,那么它也可能适用于图片的其他区域。也就是说,如果你用一个3×3的过滤器检测垂直边缘,那么图片的左上角区域,以及旁边的各个区域都可以使用这个3×3的过滤器。每个特征检测器以及输出都可以在输入图片的不同区域中使用同样的参数,以便提取垂直边缘或其它特征。假如有一个这样的数据集,其左上角和右下角可能有不同分布,也有可能稍有不同,但很相似,整张图片共享特征检测器,提取效果也很好。
第二个方法是使用稀疏连接。例如,下图中右边的0是通过3×3的卷积计算得到的,它只依赖于左边对应的3×3的输入的单元格,仅与36个输入特征中9个相连接。而其它像素值都不会对输出产生任影响,这就是稀疏连接的概念。
神经网络可以通过这两种机制减少参数,以便我们用更小的训练集来训练它,从而预防过度拟合。你们也可能听过,卷积神经网络善于捕捉平移不变。通过观察可以发现,向右移动两个像素,图片依然清晰可见,因为神经网络的卷积结构使得即使移动几个像素,这张图片依然具有非常相似的特征,应该属于同样的输出标记。