卷积神经网络(Convolutional Neural Networks, CNN)是计算机视觉技术最经典的模型结构。

虽然使用经典的全连接神经网络可以提升一定的准确率,但对于计算机视觉问题,效果最好的模型仍然是卷积神经网络。卷积神经网络针对视觉问题的特点进行了网络结构优化,更适合处理视觉问题。

卷积神经网络由多个卷积层和池化层组成,如下图所示。卷积层负责对输入进行扫描以生成更抽象的特征表示,池化层对这些特征表示进行过滤,保留最关键的特征信息。
📃 卷积神经网络 - 图1
使用卷积神经网络识别MNIST手写字体

卷积神经网络是目前计算机视觉中使用最普遍的模型结构。卷积神经网络的一些基础模块包括:

  • 卷积(Convolution)
  • 池化(Pooling)
  • ReLU激活函数
  • 批归一化(Batch Normalization)
  • 丢弃法(Dropout)

下图是一个典型的卷积神经网络结构,多层卷积和池化层组合作用在输入图片上,在网络的最后通常会加入一系列全连接层,ReLU激活函数一般加在卷积或者全连接层的输出上,网络中通常还会加入Dropout来防止过拟合。

📃 卷积神经网络 - 图2
说明:
**
在卷积神经网络中,计算范围是在像素点的空间邻域内进行的,卷积核参数的数目也远小于全连接层。卷积核本身与输入图片大小无关,它代表了对空间邻域内某种特征模式的提取。比如,有些卷积核提取物体边缘特征,有些卷积核提取物体拐角处的特征,图像上不同区域共享同一个卷积核。当输入图片大小不一样时,仍然可以使用同一个卷积核进行操作。

计算机视觉

计算机视觉作为一门让机器学会如何去“看”的学科,具体的说,就是让机器去识别摄像机拍摄的图片或视频中的物体,检测出物体所在的位置,并对目标物体进行跟踪,从而理解并描述出图片或视频里的场景和故事,以此来模拟人脑视觉系统。因此,计算机视觉也通常被叫做机器视觉,其目的是建立能够从图像或者视频中“感知”信息的人工系统。

计算机视觉的算法


  • 图像分类:图像分类算法的经典模型结构包括:LeNet、AlexNet、VGG、GoogLeNet、ResNet。
  • 目标检测:YOLO-V3算法。


计算机视觉的子任务

📃 卷积神经网络 - 图3

  • (a) Image Classification: 图像分类,用于识别图像中物体的类别(如:bottle、cup、cube)。
  • (b) Object Localization: 目标检测,用于检测图像中每个物体的类别,并准确标出它们的位置。
  • (c) Semantic Segmentation: 图像语义分割,用于标出图像中每个像素点所属的类别,属于同一类别的像素点用一个颜色标识。
  • (d) Instance Segmentation: 实例分割,值得注意的是,(b)中的目标检测任务只需要标注出物体位置,而(d)中的实例分割任务不仅要标注出物体位置,还需要标注出物体的外形轮廓。


卷积(Convolution)

卷积是数学分析中的一种积分变化的方法,在图像处理中采用的是卷积的离散形式。这里需要说明的是,在卷积神经网络中,卷积层的实现方式实际上是数学中定义的互相关 (cross-correlation)运算,与数学分析中的卷积定义有所不同,这里跟其他框架和卷积神经网络的教程保持一致,都使用互相关运算作为卷积的定义,具体的计算过程如下图所示。
📃 卷积神经网络 - 图4

说明:

卷积核(kernel)也被叫做滤波器(filter)**,假设卷积核的高和宽分别为📃 卷积神经网络 - 图5📃 卷积神经网络 - 图6,则将称为📃 卷积神经网络 - 图7卷积,比如3×5卷积,就是指卷积核的高为3, 宽为5。

卷积核的计算过程可以用下面的数学公式表示,其中 𝑎 代表输入图片, 𝑏 代表输出特征图,𝑤 是卷积核参数,它们都是二维数组,📃 卷积神经网络 - 图8 表示对卷积核参数进行遍历并求和。
📃 卷积神经网络 - 图9

填充(padding)

在上面的例子中,输入图片尺寸为3×3,输出图片尺寸为2×2,经过一次卷积之后,图片尺寸变小。卷积输出特征图的尺寸计算方法如下(卷积核的高和宽分别为📃 卷积神经网络 - 图10📃 卷积神经网络 - 图11):

📃 卷积神经网络 - 图12
📃 卷积神经网络 - 图13

比如输入尺寸为4,卷积核大小为3时,输出尺寸为4−3+1=24−3+1=2。

如果经过多次卷积,输出图片尺寸会不断减小。为了避免卷积之后图片尺寸变小,通常会在图片的外围进行填充(padding),如下图所示。
📃 卷积神经网络 - 图14

  • 如图(a)所示:填充的大小为1,填充值为0。填充之后,输入图片尺寸从📃 卷积神经网络 - 图15变成了📃 卷积神经网络 - 图16,使用📃 卷积神经网络 - 图17的卷积核,输出图片尺寸为📃 卷积神经网络 - 图18
  • 如图(b)所示:填充的大小为2,填充值为0。填充之后,输入图片尺寸从📃 卷积神经网络 - 图19变成了📃 卷积神经网络 - 图20,使用📃 卷积神经网络 - 图21的卷积核,输出图片尺寸为📃 卷积神经网络 - 图22

如果在图片高度方向,在第一行之前填充📃 卷积神经网络 - 图23行,在最后一行之后填充📃 卷积神经网络 - 图24行;在图片的宽度方向,在第1列之前填充📃 卷积神经网络 - 图25列,在最后1列之后填充📃 卷积神经网络 - 图26列;则填充之后的图片尺寸为📃 卷积神经网络 - 图27。经过大小为📃 卷积神经网络 - 图28的卷积核操作之后,输出图片的尺寸为:
📃 卷积神经网络 - 图29
📃 卷积神经网络 - 图30

在卷积计算过程中,通常会在高度或者宽度的两侧采取等量填充,即📃 卷积神经网络 - 图31📃 卷积神经网络 - 图32,上面计算公式也就变为:
📃 卷积神经网络 - 图33
📃 卷积神经网络 - 图34

卷积核大小通常使用1,3,5,7这样的奇数,如果使用的填充大小为📃 卷积神经网络 - 图35📃 卷积神经网络 - 图36,则卷积之后图像尺寸不变。例如当卷积核大小为3时,padding大小为1,卷积之后图像尺寸不变;同理,如果卷积核大小为5,padding大小为2,也能保持图像尺寸不变。

步幅(stride)

上面示例中卷积核每次都只滑动一个像素点,这是步幅为1的特殊情况。下图是步幅为2的卷积过程,卷积核在图片上移动时,每次移动大小为2个像素点。
📃 卷积神经网络 - 图37
当宽和高方向的步幅分别为📃 卷积神经网络 - 图38📃 卷积神经网络 - 图39时,输出特征图尺寸的计算公式是:
📃 卷积神经网络 - 图40
📃 卷积神经网络 - 图41

假设输入图片尺寸是📃 卷积神经网络 - 图42,卷积核大小📃 卷积神经网络 - 图43,填充📃 卷积神经网络 - 图44,步幅为📃 卷积神经网络 - 图45,则输出特征图的尺寸为:
📃 卷积神经网络 - 图46
📃 卷积神经网络 - 图47

感受野(Receptive Field)

输出特征图上每个点的数值,是由输入图片上大小为📃 卷积神经网络 - 图48的区域的元素与卷积核每个元素相乘再相加得到的,所以输入图像上📃 卷积神经网络 - 图49区域内每个元素数值的改变,都会影响输出点的像素值。我们将这个区域叫做输出特征图上对应点的感受野。感受野内每个元素数值的变动,都会影响输出点的数值变化。比如单层📃 卷积神经网络 - 图50卷积对应的感受野大小就是📃 卷积神经网络 - 图51

对于单层卷积来说,感受野的大小就是卷积核的大小。
📃 卷积神经网络 - 图52
对于多层卷积来说,感受野的大小往往比卷积核大。
📃 卷积神经网络 - 图53

多个输入输出通道

前面介绍的卷积计算过程比较简单,实际应用时,处理的问题要复杂的多。例如:对于彩色图片有RGB三个通道,需要处理多输入通道的场景。输出特征图往往也会具有多个通道,而且在神经网络的计算中常常是把一个批次的样本放在一起计算,所以卷积算子需要具有批量处理多输入和多输出通道数据的功能,下面将分别介绍这几种场景的操作方式。

多输入通道场景

上面的例子中,卷积层的数据是一个2维数组,但实际上一张图片往往含有RGB三个通道,要计算卷积的输出结果,卷积核的形式也会发生变化。假设输入图片的通道数为📃 卷积神经网络 - 图54,输入数据的形状是📃 卷积神经网络 - 图55,计算过程如下图所示。

📃 卷积神经网络 - 图56

  1. 对每个通道分别设计一个2维数组作为卷积核,卷积核数组的形状是📃 卷积神经网络 - 图57
  2. 对任一通道📃 卷积神经网络 - 图58,分别用大小为📃 卷积神经网络 - 图59的卷积核在大小为📃 卷积神经网络 - 图60的二维数组上做卷积。
  3. 将这📃 卷积神经网络 - 图61个通道的计算结果相加,得到的是一个形状为📃 卷积神经网络 - 图62的二维数组。

多输出通道场景

一般来说,卷积操作的输出特征图也会具有多个通道📃 卷积神经网络 - 图63,这时我们需要设计📃 卷积神经网络 - 图64个维度为📃 卷积神经网络 - 图65的卷积核,卷积核数组的维度是📃 卷积神经网络 - 图66,如下图所示。
📃 卷积神经网络 - 图67

  1. 对任一输出通道📃 卷积神经网络 - 图68,分别使用上面描述的形状为📃 卷积神经网络 - 图69的卷积核对输入图片做卷积。
  2. 将这📃 卷积神经网络 - 图70个形状为📃 卷积神经网络 - 图71的二维数组拼接在一起,形成维度为📃 卷积神经网络 - 图72的三维数组。

通常将卷积核的输出通道数叫做卷积核的个数。

批量操作

在卷积神经网络的计算中,通常将多个样本放在一起形成一个mini-batch进行批量操作,即输入数据的维度是📃 卷积神经网络 - 图73由于会对每张图片使用同样的卷积核进行卷积操作,卷积核的维度与上面多输出通道的情况一样,仍然是📃 卷积神经网络 - 图74,输出特征图的维度是📃 卷积神经网络 - 图75,如下图所示。
📃 卷积神经网络 - 图76

池化(Pooling)

池化是使用某一位置的相邻输出的总体统计特征代替网络在该位置的输出,其好处是当输入数据做出少量平移时,经过池化函数后的大多数输出还能保持不变。由于池化之后特征图会变得更小,如果后面连接的是全连接层,能有效的减小神经元的个数,节省存储空间并提高计算效率。 如下图所示,将一个2×2的区域池化成一个像素点。通常有两种方法,平均池化和最大池化。
📃 卷积神经网络 - 图77

  • 如图(a):平均池化。这里使用大小为📃 卷积神经网络 - 图78的池化窗口,每次移动的步幅为2,对池化窗口覆盖区域内的像素取平均值,得到相应的输出特征图的像素值。
  • 如图(b):最大池化。对池化窗口覆盖区域内的像素取最大值,得到输出特征图的像素值。当池化窗口在图片上滑动时,会得到整张输出特征图。池化窗口的大小称为池化大小,用📃 卷积神经网络 - 图79表示。在卷积神经网络中用的比较多的是窗口大小为📃 卷积神经网络 - 图80,步幅为2的池化。

与卷积核类似,池化窗口在图片上滑动时,每次移动的步长称为步幅,当宽和高方向的移动大小不一样时,分别用📃 卷积神经网络 - 图81📃 卷积神经网络 - 图82表示。也可以对需要进行池化的图片进行填充,填充方式与卷积类似,假设在第一行之前填充📃 卷积神经网络 - 图83行,在最后一行后面填充📃 卷积神经网络 - 图84行。在第一列之前填充📃 卷积神经网络 - 图85列,在最后一列之后填充📃 卷积神经网络 - 图86列,则池化层的输出特征图大小为:
📃 卷积神经网络 - 图87
📃 卷积神经网络 - 图88

在卷积神经网络中,通常使用📃 卷积神经网络 - 图89大小的池化窗口,步幅也使用2,填充为0,则输出特征图的尺寸为:
📃 卷积神经网络 - 图90
📃 卷积神经网络 - 图91

通过这种方式的池化,输出特征图的高和宽都减半,但通道数不会改变。

批归一化(BatchNorm)

批归一化方法(Batch Normalization,BatchNorm)是由Ioffe和Szegedy于2015年提出的,已被广泛应用在深度学习中,其目的是对神经网络中间层的输出进行标准化处理,使得中间层的输出更加稳定。

通常我们会对神经网络的数据进行标准化处理,处理后的样本数据集满足均值为0,方差为1的统计分布,这是因为当输入数据的分布比较固定时,有利于算法的稳定和收敛。对于深度神经网络来说,由于参数是不断更新的,即使输入数据已经做过标准化处理,但是对于比较靠后的那些层,其接收到的输入仍然是剧烈变化的,通常会导致数值不稳定,模型很难收敛。BatchNorm能够使神经网络中间层的输出变得更加稳定,并有如下三个优点:

  • 使学习快速进行(能够使用较大的学习率)
  • 降低模型对初始值的敏感性
  • 从一定程度上抑制过拟合

BatchNorm主要思路是在训练时以mini-batch为单位,对神经元的数值进行归一化,使数据的分布满足均值为0,方差为1。具体计算过程如下:

1. 计算mini-batch内样本的均值
📃 卷积神经网络 - 图92

其中📃 卷积神经网络 - 图93表示mini-batch中的第📃 卷积神经网络 - 图94个样本。

2. 计算mini-batch内样本的方差
📃 卷积神经网络 - 图95

上面的计算公式先计算一个批次内样本的均值📃 卷积神经网络 - 图96和方差📃 卷积神经网络 - 图97,然后再对输入数据做归一化,将其调整成均值为0,方差为1的分布。

3. 计算标准化之后的输出
📃 卷积神经网络 - 图98

其中📃 卷积神经网络 - 图99是一个微小值(例如📃 卷积神经网络 - 图100),其主要作用是为了防止分母为0。

4. 缩放和平移 (仿射变换)
**
如果强行限制输出层的分布是标准化的,可能会导致某些特征模式的丢失,所以在标准化之后,BatchNorm会紧接着对数据做缩放和平移。
📃 卷积神经网络 - 图101

其中📃 卷积神经网络 - 图102📃 卷积神经网络 - 图103是可学习的参数,可以赋初始值📃 卷积神经网络 - 图104, 📃 卷积神经网络 - 图105,在训练过程中不断学习调整。

计算过程举例

例如输入mini-batch包含3个样本,每个样本有2个特征,分别是:

📃 卷积神经网络 - 图106

对每个特征分别计算mini-batch内样本的均值:

📃 卷积神经网络 - 图107

则样本均值是:
📃 卷积神经网络 - 图108

对于上述给定的输入数据📃 卷积神经网络 - 图109,计算出每个特征对应的方差:

📃 卷积神经网络 - 图110

📃 卷积神经网络 - 图111

则样本方差是:
📃 卷积神经网络 - 图112

对于上述给定的输入数据📃 卷积神经网络 - 图113,可以计算出标准化之后的输出:

📃 卷积神经网络 - 图114

丢弃法(Dropout)

丢弃法(Dropout)是深度学习中一种常用的抑制过拟合的方法,其做法是在神经网络学习过程中,随机删除一部分神经元。训练时,随机选出一部分神经元,将其输出设置为0,这些神经元将不对外传递信号。

下图是Dropout示意图,左边是完整的神经网络,右边是应用了Dropout之后的网络结构。应用Dropout之后,会将标了×的神经元从网络中删除,让它们不向后面的层传递信号。在学习过程中,丢弃哪些神经元是随机决定,因此模型不会过度依赖某些神经元,能一定程度上抑制过拟合。
📃 卷积神经网络 - 图115
在预测场景时,会向前传递所有神经元的信号,可能会引出一个新的问题:训练时由于部分神经元被随机丢弃了,输出数据的总大小会变小。比如:计算其📃 卷积神经网络 - 图116范数会比不使用Dropout时变小,但是预测时却没有丢弃神经元,这将导致训练和预测时数据的分布不一样。为了解决这个问题,通常采用如下两种方法:

  • downgrade_in_infer

训练时以比例📃 卷积神经网络 - 图117随机丢弃一部分神经元,不向后传递它们的信号;预测时向后传递所有神经元的信号,但是将每个神经元上的数值乘以📃 卷积神经网络 - 图118

  • upscale_in_train

训练时以比例📃 卷积神经网络 - 图119随机丢弃一部分神经元,不向后传递它们的信号,但是将那些被保留的神经元上的数值除以📃 卷积神经网络 - 图120;预测时向后传递所有神经元的信号,不做任何处理。