3.1.2 卷积层
卷积层与全连接层不同,它保留了输入图像的空间特征,仍以一张32×32×3的图像为例,卷积层的输入就是32×32×3的矩阵,不需要做任何改变。卷积层的主要作用是提取特征。我们将卷积层的输入输出数据称为特征图,那么卷积层的输入数据就是输入特征图,输出数据就是输出特征图。
在卷积层中,对图像进行的处理就是卷积运算。在卷积运算中,我们需要引入一个新的概念:卷积核(kernel,常简称为卷积,有时也称为滤波器)。卷积核的尺寸可以根据实际需要自行定义,通常设为(1,1)(3,3)、(5,5)等。值得注意的是,尺寸较大的卷积核带来的计算量会比较大,因此目前主流的卷积核尺寸都相对较小。卷积核的通道个数一般设置为与输入图像通道数一致(如果输入的图像是灰度图,则通道数为1,如果输入的图像是彩色图,则通道数为3)。
下面我们来探讨卷积运算的过程。让卷积核在输入特征图上依次滑动,滑动方向为从左到右,从上到下。每滑动一次,卷积核就和滑窗位置对应的输入特征图x做一次点乘计算(将各个位置上卷积核的元素和输入特征图对应位置的元素先相乘再求和),并将得到的数值保存到输出特征图对应的位置上,最终得到卷积运算的输出(形成完整的输出特征图)。在CNN中,卷积核除了有权重参数之外,也存在偏置。偏置通常只有一个(1,1),它会被加到应用卷积核的所有元素上。
介绍了这么多概念,下面我们通过一个示例加深理解。本例中,输入特征图的大小是(4,4),卷积核的大小是(3,3),输出的特征图的大小是(2,2)。对于输入特征图数据,以一定间隔的滑动卷积核进行卷积运算,这里的滑动间隔为1,如图3-2所示。
图3-2 卷积运算示例
我们先来观察图3-3深色的部分(与卷积核的尺寸保持一致)。将输入特征图各个位置上的元素与卷积核对应的元素先相乘再求和,并将这个结果保存到输出特征图相应的位置上。具体计算逻辑(以第一次运算作为示例)为1×1+2×0+3×3+0×0+1×1+2×2+2×2+1×1+0×0=20。以此类推,过程如图3-3所示。
图3-3 卷积运算详细流程
最后加上偏置,如图3-4所示。
图3-4 卷积运算上应用偏置
这里需要提到另一个概念:步长,即卷积核在输入特征图上需要移动的像素。如上述例子的步长为1时,卷积核每次只移动1个像素,计算过程不会跳过任何一个像素;而步长为2时,卷积核会跳过1个像素,每次移动2个像素。
为方便大家理解,我们先看一维卷积运算的情况,如图3-5a所示,输入一个(1,7)的向量及其对应的数值。我们定义一维卷积,尺寸为(1,3)(数值分别为10、5、11),那么经过第一次卷积操作(卷积和对应的输入做点乘)后我们得到10×5+5×2+11×6=126,故图中A对应的数值为126。
图3-5 卷积核为(1,3),步长为1的一维卷积运算过程示意图
在这个例子里,因为我们定义步长为1,所以接下来卷积移动一个格子(在图像中一个步长可以理解为一个像素)。如图3-5b所示,可以计算得到B的数值为160。以此类推,最终得到一个(1,5)的向量,如图3-5c所示。
补充说明
卷积核每次滑动覆盖的范围在图像处理中也叫作感受野,我们会在后续做详细介绍。
接着,我们扩展到步长为2的情况,如图3-6所示,同样是(1,7)的输入向量,每次移动两个格子,即卷积从“5,2,6”移动到“6,10,7”,然后再移动到“7,12,8”,完成所有的卷积操作后,最终得到一个(1,3)的向量。
图3-6 卷积核为(1,3),步长为2的一维卷积运算过程示意图
下面介绍另一个重要的概念:填充。填充指的是向输入特征图的周围填入固定的数据(比如0)。使用填充可以调整输出特征图的大小。举个例子,对大小为(4,4)的输入特征图应用(3,3)的卷积核,如果不使用填充,则输出特征图的尺寸为(2,2)。在反复进行多次卷积运算之后,深度网络的输出特征图的尺寸有可能在某个时刻变为1,导致无法再进行卷积运算。为了避免这样的情况出现,就需要进行填充。针对刚才的例子,我们将填充大小设为1,这样输出特征图的尺寸就能保持原来的(4,4),卷积运算可以在空间尺寸不变的情况下将数据传递给下一层。
介绍了卷积层,我们再来看看什么是卷积神经网络。如图3-7所示,卷积神经网络由一系列卷积层经过激活所得。
接下来我们学习一种更为通用的卷积形式,在(7,7)的输入图像周边做1个像素的填充(padding=1),如图3-8所示,那么步长为1,卷积核为(3,3)的输出特征层为(7,7)。我们给出通用卷积层的计算公式:输入图像为,W、H、D分别表示图像的宽、高、通道数;卷积层中卷积核的大小为(F,F),步长为S,填充大小为P,卷积核的个数为K,那么经过卷积运算后输出图像的宽、高、通道数分别为,,D2=K。
图3-7 卷积神经网络示意图
图3-8 卷积核为(3,3),填充大小为1的卷积运算示意图
至此,卷积层的基本运算介绍完毕,那么卷积层的参数个数是如何计算的呢?假设输入的图像为彩色图、3通道,并且使用了10个卷积核,每个卷积核的大小为(4,4),那么这个卷积层的参数个数为4×4×3×10+10=490(最后的10为偏置个数,一般偏置个数与卷积核数量保持一致)。
与传统神经网络不同的是,卷积层的计算是含有空间信息的。
对于PyTorch这个深度学习框架来说,卷积函数已经被很好地封装了。二维卷积nn.Conv2d用于处理图像数据,对宽度和高度都进行卷积运算,其定义如下。
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
·in_channels(int):输入特征图的通道数。
·out_channels(int):输出特征图的通道数。
·kernel_size(int or tuple):卷积核的大小。
·stride(int or tuple,optional):卷积核的步长,默认为1。
·padding(int or tuple,optional):输入的每一条边补充0的层数,默认为0。
·dilation(int or tuple,optional):卷积核元素间的距离,默认为1。
·groups(int,optional):将原始输入通道划分成的组数,默认为1。
·bias(bool,optional):默认为True,表示输出的bias可学习。
示例如下。
self.conv1 = nn.Conv2d(1, 6, 5) # 输入通道数为1,输出通道数为6,卷积核为(5,5)