引言

之前接触的都是全连接神经网络,它来处理图像时,会存在以下问题:

  1. 将图像展开为向量会丢失空间信息
  2. 参数太多:如果输入图像大小为100×100×3(RGB),在全连接神经网络中,第一个隐藏层的每个神经元到输入层都有 30000 个权重参数。随着神经元数量和隐藏层个数的增多,参数的规模也会急剧增加。这会导致整个神经网络的训练效率非常低,也很容易出现过拟合。
  3. 局部不变性特征:自然图像中的物体都具有局部不变性特征,比如尺度缩放、平移、旋转等操作不影响其语义信息。而全连接神经网络很难提取这些局部不变性特征,一般需要进行数据增强来提高性能。

卷积神经网络(Convolutional Neural Network,CNN)的设计灵感来自于生物学中的视觉系统,旨在模拟人类视觉处理的方式。在过去的几年中,CNN已经在图像识别、目标检测、图像生成和许多其他领域取得了显著的进展,成为了计算机视觉和深度学习研究的重要组成部分。

卷积神经网络

卷积层是由全连接层演变而来的,在全连接层中,每个输出通过权值与所有输入相连。而在视觉识别任务中,关键性的图像特征、边缘、角点等只占据了整张图像的一小部分,图像中相距较远的的两个像素有相互影响的可能性较小。因此,在卷积层中,每个输出神经元在空间上只和邻域的一小部分输入神经元相连。

卷积

深度学习里面的卷积(Convolution),其实是数学上的互相关(cross-correlation)运算,节省了不必要的镜像翻转开销。

ConvolutionKernel

给定一个小小的权重矩阵 WW,用于在输入图像 XX 上滑动,并对图像的局部区域进行加权求和,最后的结果组成一个矩阵,其中没有对核进行翻转。写作

Y=WXY=W*X

其中 * 表示卷积符号,权重矩阵 WW 称为滤波器(Filter)或卷积核(Convolution Kernel)

一幅图像在经过卷积操作后得到结果称为特征映射图(Feature Map)。不同的卷积核可以提取不同的特征图,例如边缘、纹理等。下图展示了垂直边缘检测和水平边缘检测

Vertical_edge_detection

很明显,这张图片中间有一个非常强烈的垂直边缘。

Horizontal_edge_detection

其实,还有许多其他类型的卷积核

[w1w2w3w4w5w6w7w8w9]\begin{bmatrix} w_1&w_2&w_3\\w_4&w_5&w_6\\w_7&w_8&w_9 \end{bmatrix}

我们可以通过反向传播来训练其中的参数,从而学习到比任何手工编码都好的卷积核。

步长和填充

在卷积的标准定义基础上,还可以引入卷积步长和填充来增加卷积的多样性,可以更灵活地进行特征抽取。

步长(stride)决定了卷积核在输入特征图上移动的间隔大小。步长不仅影响卷积后特征图的尺寸,还关系到模型的计算量。下图给出了步长为 2 的卷积运算

在实际应用中,步长通常设置为1或2。步长为1时,适用于细粒度特征的提取;步长为2时,可以减小特征图的尺寸,适用于降低计算量。

卷积操作很明显有两个缺点:(1) 图像都会缩小;(2) 中心区域的信息有很多重叠,但图像的角落或边缘却很少被使用,相当于丢弃了图像边缘的大量信息。

为了解决这个问题,可以在应用卷积操作之前,对图像进行填充。填充(Padding)是指在图像边界两端进行补零。

padding

通过填充的方法,当卷积核扫描输入数据时,它能延伸到边缘以外的伪像素,从而使输出和输入大小相同。

假设输入特征图的大小为 n×nn\times n ,卷积核大小为 f×ff\times f,卷积步长为 ss ,填充为 pp 。输出特征图的尺寸为:

o=n+2pfs+1o=\left\lfloor \frac{n + 2p - f}{s} + 1 \right\rfloor

填充后的输出一般只保留原始输入的大小。所以一般填充

p=f12p=\frac{f-1}{2}

实际上卷积核的大小总是奇数,避免了不对称填充。

多通道卷积

之前的例子都只是灰度图,实际上,大多数输入图像都有 RGB 3个通道。输入图像由单个矩阵扩展成有序排列的三个矩阵,在神经网络中称为三维张量。三个维度分别称为宽度(width)、高度(height)和通道数(channels),通道数也称为深度(depth)。

这时我们需要使用三维卷积核来计算,卷积核的通道数必须与输入数据的通道数相同。每一个通道的图像与卷积核对应的每一个通道进行卷积运算,最后相加,形成一个单通道输出。

在上面的多通道卷积中,输出的卷积结果只有1个通道,把卷积的整个过程抽象表示如下:

这个特征图代表从输入图像中提取出来的一种特征。而一般在输入图像上只提取一种特征是完全不够的,往往需要在输入图像上获取更多的特征信息,即要获得多个特征图,那么就需要多组卷积核在图像上进行卷积计算。下图中使用了两组卷积核计算得到了2个特征图。

如果同时使用多个卷积核,这时我们可以把这些最终的单通道输出堆叠成一个三维总输出。

卷积层

在卷积层(Convolutional Layer)中有两个重要的性质:

  • 局部连接(local connectivity):在卷积层中的每一个神经元都只和前一层中某个局部窗口内的神经元相连, 构成一个局部连接网络。 卷积层和前一层之间的权重参数大大减少。
  • 权重共享(weight sharing):一个卷积核表示了在图像中提取某种特定的局部特征的能力,比如纹理特征等。也就是说卷积核具有了这种能力,无论在图像的哪个地方都可以起作用。即让同一特征图上的神经元使用相同的权重,从而大幅减少需要训练的参数数目。如果要提取多种特征就需要使用多个不同的卷积核。

假设输入的特征图大小为 dW×dH×dCd_W\times d_H\times d_C 的三维张量 XX,使用 KKf×f×dCf\times f\times d_C 的卷积核,可叠加成一个 f×f×dC×Kf\times f\times d_C\times K 形状的四维张量 WW。则卷积层首先进行线性运算

Z=WX+bZ=W*X+b

其中 bb​ 是每个卷积核的偏置组成的一维张量。再经过非线性激活函数得到最终的特征图

A=g(Z)A=g(Z)

如果卷积核的步长和填充分别为 s,ps,p ,输出特征图的大小为

dW+2pfs+1×dH+2pfs+1×K\left\lfloor \frac{d_W+2p-f}{s}+1 \right\rfloor \times \left\lfloor \frac{d_H+2p-f}{s}+1 \right\rfloor \times K

由于局部连接和权重共享,共需要 f×f×dC×K+Kf\times f\times d_C\times K+K 个参数,参数个数和神经元的数量无关。 这使得整个神经网络的参数大大减小,提高了整个网络的训练性能。

池化层

池化层(Pooling)作用是基于局部相关性原理进行亚采样,从而在减少数据量的同时保留有用信息。可以看作是对图像的一次“有损压缩”,因为在实际的训练中,我们并不需要对图像中的每一个细节都进行特征提取和训练,所以池化的作用就是更进一步的信息抽象和特征提取,当然也会减小数据的处理量。常见的池化类型包括:

  • 最大池化(Max Pooling):选取局部区域内的最大激活值,更多的保留图像的纹理信息。
  • 平均池化(Average Pooling):计算局部区域内的平均值,更多的保留图像的背景信息。

池化层也有一个滤波器来对特征图进行扫描,扫描的过程中同卷积层一样。因为池化独立应用于每个通道,输出的通道数还是不变的。

假设输入特征图的大小为 dW×dH×dCd_W\times d_H\times d_C ,过滤器大小为 f×ff\times f,卷积步长为 ss ,填充为 pp 。输出特征图的尺寸为:

dW+2pfs+1×dH+2pfs+1×dC\left\lfloor \frac{d_W+2p-f}{s}+1 \right\rfloor \times \left\lfloor \frac{d_H+2p-f}{s}+1 \right\rfloor \times d_C

其中,最常用的是最大池化,使用尺寸2x2的滤波器,以步长为2来对每个渠道进行降采样。如下图示例所示:

max_pool

池化操作降低了图像的分辨率,降低计算量,提高模型的泛化能力,并减少过拟合现象。过大的采样区域也会急剧减少神经元的数量,造成过多的信息损失。

1×1卷积

1x1卷积也称为点卷积(Pointwise Convolution),是一种在深度学习中常用的卷积操作。它的核心思想是使用1x1的卷积核对特征图进行卷积,以此来改变特征图的通道数,实现跨通道的信息整合和参数量的减少。

1x1卷积实际上是卷积核和每个像素点的多个通道的点积。这种操作可以看作是在通道维度上的全连接层,它允许模型学习通道之间的复杂关系,同时显著减少参数数量。比如一张500×500且通道数为100的图片在20个filter上做1×1的卷积,输出特征图的尺寸变为500×500×20。

卷积神经网络

目前的卷积神经网络一般是由卷积层、池化层和全连接层交叉堆叠而成的。

  • 输入层(Input):为原始图像,三维或二维的张量。
  • 卷积层(Conv):由一组可学习的卷积核组成,每个卷积核具有kernel size、padding、stride等参数。目前,卷积网络的整体结构趋向于使用更小的卷积核 ,常见尺寸为 3x3 或 5x5。
  • 池化层(Pooling):通常对卷积层后输出的特征图进行下采样操作。没有参数,不可学习。
  • 全连接层(Fully Connected, FC):需要将上一层的输出向量flatten成一个一维的向量,然后输入到全连接层中。
Activation shape Activation size # parameters
Input 32x32x3 3,072 0
Conv1 28x28x8 6,272 208
Pool1 14x14x8 1,568 0
Conv2 10x10x16 1,600 416
Pool2 5x5x16 400 0
FC3 120x1 120 48,001
FC4 84x1 84 10,081
Softmax 10x1 10 841

因为池化层没有可学习的参数,按照惯例,通常将Conv和随后的Pool放在一起成为一层。关于网络的设计,根据经验,通常从较大的图像开始,随着神经网络的深入,高度和宽度逐渐下降,而频道的数量一般会增加,但激活的大小可能逐渐减小。如果降的太快,通常对性能不好。

卷积神经网络是受生物学上感受野机制启发而提出的。感受视野(Receptive Field) 指的是卷积神经网络每一层输出的特征图上每个元素映射回输入层图像上的区域大小。卷积核的大小决定了感受视野的范围。

感受视野的范围越大表示其能接触到的原始图像范围就越大,也意味着它能学习更为全局的特征信息;相反,范围越小则表示其所包含的特征越趋向局部和细节。因此感受视野的范围可以用来大致判断每一层的抽象层次。并且我们可以很明显地知道网络越深,神经元的感受视野越大。由此可知,深度卷积神经网络中靠前的层感受视野较小,提取到的是图像的纹理、边缘等局部的、通用的特征;靠后的层由于感受视野较大,提取到的是图像更深层次、更具象的特征。因此在迁移学习中常常会将靠前的层的参数冻结(不参与训练,因为他们在迁移到新的场景之前已经具备了提取通用特征的能力),来节省训练的时间和算力消耗。

下面给出感受视野的计算公式:

RF[l]=RF[l1]+(f[l]1)×i=1l1siRF^{[l]}=RF^{[l-1]}+(f^{[l]}-1)\times \prod_{i=1}^{l-1}s_i

其中RFRF 为感受视野大小,f[l]f^{[l]} 为当前层卷积核大小,最后一项连乘项则表示之前卷积层的步长乘积。

反向传播算法

在卷积网络中,参数为卷积核中权重以及偏置,池化层没有参数,不需要学习。和全连接前馈网络类似,卷积网络也可以通过反向传播算法来进行参数学习。

给定包含 NN 个样本的数据集 DD 。其中,每个样本是形状为大小为 dW×dH×dCd_W\times d_H\times d_C 的三维张量。

假设 cost function 为

J=1Ni=1N(y^i,yi)J=\frac{1}{N} \sum_{i = 1}^N\ell(\hat y_i,y_i)

假设第 ll 层输入的特征图为 A[l1]A^{[l-1]} ,使用 K[l]K^{[l]} 个卷积核叠加成一个四维张量 W[l]W^{[l]}。通过卷积计算得到第 ll 层的线性输出

Z[l]=W[l]A[l1]+b[l]Z^{[l]}=W^{[l]}*A^{[l-1]}+b^{[l]}

其中 b[l]b^{[l]} 是由 K[l]K^{[l]} 个卷积核的偏置组成的一维张量。再经过非线性激活函数得到最终的特征图

A[l]=g[l](Z[l])A^{[l]}=g^{[l]}(Z^{[l]})

根据链式法则,可证明

JW[l]=JZ[l]A[l1]whereJZ[l]=JA[l]g[l] (Z[l])\frac{\partial J}{\partial W^{[l]}}= \frac{\partial J}{\partial Z^{[l]}} * A^{[l-1]}\quad \text{where}\quad \frac{\partial J}{\partial Z^{[l]}}= \frac{\partial J}{\partial A^{[l]}}\odot g^{[l]}\ '(Z^{[l]})

关于池化层的反向传播: 对于最大池化来说,max\max 函数的反向传播可以简单理解为将梯度只沿最大的数回传。因此,在向前传播经过池化层的时候,通常会把池中最大元素的索引记录下来(有时这个也叫作道岔(switches)),这样在反向传播的时候梯度的路由就很高效。

经典卷积网络

经典的CNN网络有LeNet-5、AlexNet、VGG、GoogleNet、ResNet等。这些经典CNN网络结构中总是包含一些对于神经网络架构设计有巨大启发性的东西。

LeNet

LeNet-5由Yann LeCun在1998年提出的,是第一个成功的卷积神经网络应用,用于手写数字识别。LeNet输入为32x32的灰度图像,经过两次卷积和池化操作后,进入全连接层,最终输出为10个类别的概率。

AlexNet

AlexNet由Alex Krizhevsky等人在2012年提出,是第一个现代深度卷积网络模型,其首次使用了很多现代深度卷积网络的技术方法,比如使用 GPU 进行并行训练,采用了 ReLU 作为非线性激活函数,使用 Dropout 防止过拟合, 使用数据增强来提高模型准确率等。 AlexNet 赢得了 2012 年 ImageNet 图像分类竞赛的冠军。

VGG

VGGNet由牛津大学和Google DeepMind的研究员在2014年提出,通过重复使用简单的基础块来构建深度模型,极大的简化了神经网络架构。

VGG 块的组成规律是:连续使用多个相同的 stride 为 1,kernel 为 3×3 的卷积层后,接上一个 stride 为 2,kernel 为 2×2 的最大池化层。卷积层通过填充,始终保持输入的尺寸不变,而池化层则对其减半。

GoogLeNet

GoogLeNet由Google团队在2014年提出,通过不同大小的卷积核和池化操作提取多尺度特征。GoogLeNet在ImageNet竞赛中取得了冠军,并显著减少了参数量。

GoogleNet设计了一种称为 Inception 的卷积模块,作为基本卷积模块。结构如下图所示:

Inception 模块采用了 4 组平行的特征抽取方式, 分别为 1×1、 3×3、 5×5 的不同大小的卷积核和 3×3 的最大池化, 并将得到的特征映射在渠道上拼接 (堆叠) 起来作为输出特征映射。

GoogLeNet 证明了一件事:用更多的卷积,更深的层次可以得到更好的结构。(当然,它并没有证明浅的层次不能达到这样的效果)

ResNet

残差网络(Residual Network,ResNet)由何凯明等人在2015年提出,解决了深度网络中的梯度消失问题,是计算机视觉中最流行的体系结构。

ResNet 引入了残差块(residual blocks),允许你从一个图层获取激活,然后通过残差连接 (Residual Connection)垮层传递到另一个图层。我们先来看看残差块的设计:

若忽略残差块的影响

a[l+2]=g(z[l+2]+a[l])g(a[l])=a[l]a^{[l+2]}=g(z^{[l+2]}+a^{[l]})\approx g(a^{[l]})=a^{[l]}

仅仅是复制 a[l]a^{[l]} 的值到 a[l+2]a^{[l+2]}。这是因为 ResNet 采用 ReLU 激活函数,激活值始终大于0。这意味着添加残差块,可以训练更深的神经网络,而不会真正损害神经网络的能力。若学到有用的东西,甚至能提升模型性能。

DenseNet 可以看作是 ResNet 的发展创新,关键区别在于,DenseNet 输出是渠道连接而不是简单相加。