本文总结卷积神经网络及其变体,参考书目为《动手学深度学习PyTorch版》,本文附的例子都来自此书,书本的官方地址为动手学深度学习,感兴趣的朋友可以直接去官网看,更加详细,还附有实现的代码和李沐的讲解视频。
CNN
- 互相关操作
以一个例子介绍互相关操作,假设输入大小是3×3,核函数大小为2×2,蓝色高亮部分就是第一个数的运算,输入中的高亮部分和核函数对应部分相乘再求和,即0×0+1×1+3×2+4×3=19,其他三个位置类似。
可以发现经过互相关运算,输出的大小小于输入(可以理解为特征提取的过程),这和卷积核的大小相关,关于输出大小的计算有以下公式,其中n_h、n_w是输入的高和宽,k_h、k_w是卷积核的高和宽。
卷积层的主要作用就是进行互相关运算,卷积核是其中的关键,那么如何得到合理的卷积核呢?其实卷积核会在反向传播中作为参数自动更新,通过训练得到。 - 填充和步幅
上图的例子中,可以发现输入张量的四个边缘位置(0,2,6,8)都只参与一次运算而其他位置都参与了两次,这样一来会导致丢失边缘特征导致特征提取不正确,因此引入填充(padding)的方法,即在原始输入的周围用0拓展一圈或多圈,这样边缘位置也可以被公平地计算到,如图所示,在3×3的输入拓展了一圈。
经过填充后的输入计算公式如下,注意,这里的p_h指的是在高度上填充的总数,如在上例中高度总共填充了两行,因此p_h=2,p_w同理。
上述两例中进行互相关运算时每次都是移动一个位置,有时候为了高效计算或是缩减采样次数,可以一次移动多个位置,下图是垂直步幅为3,水平步幅为2的二维互相关运算。
这时输出的大小如下,其中是s_h垂直步幅,s_w是水平步幅。
- 多输入输出通道
上面的例子中均是单通道输入和输入,但是在实际应用中,例如图像往往是RGB三通道的,下面介绍多通道的输入和输出。
下图是两个输入通道一个输出通道的例子,(1×1+2×2+4×3+5×4)+(0×0+1×1+3×2+4×3)=56
三个输入通道和两个输出通道,使用两个1×1的卷积核
- 汇聚层(池化层)
汇聚层的主要目的有两个:降低卷积层对位置的敏感性,同时降低对空间降采样表示的敏感性。
汇聚窗口从输入的左上角开始,从左往右、从上往下的在输入张量内滑动。在汇聚窗口到达的每个位置,它计算该窗口中输入子张量的最大值或平均值。计算最大值或平均值是取决于使用了最大汇聚层还是平均汇聚层。下图是最大汇聚层的例子,汇聚窗口大小为2×2。
与卷积层一样,汇聚层也可以改变输出形状,可以通过填充和步幅以获得所需的输出形状,默认情况下,深度学习框架中的步幅与汇聚窗口的大小相同。且汇聚层的输出通道数与输入通道数相同。池化后的大小为(输入大小-汇聚层窗口大小)/步幅+1,向下取整。
这篇博客讲解的更加详细,尤其是里面的示意图是动态的非常易于理解。
卷积神经网络(CNN)详细介绍及其原理详解
LeNet
LeNet架构如下图所示,两个卷积层,两个池化层,三个全连接层,激活函数使用的是sigmoid。
每一层的具体情况可以参考下图,按照28×28的输入来看,第一个卷积层有6个卷积核,步幅为1,填充为2,按照第一节所给出的公式,经过第一次卷积后得到的特征图大小高和宽均为28-5+4+1=28,且有6个通道,卷积后会有一个sigmoid操作。
第一个池化层的池化窗口大小为2×2,步幅为2,池化后通道数不变,步幅为2相当于高和宽均缩小一半,所以输出大小为14×14。
第二个卷积层有16个10×10的卷积核,步幅为1,不进行填充,计算可得输出特征图的高和宽为14-5+1=10,通道数为16,然后进行sigmoid操作。
第二个池化层和第一个池化层一样,池化窗口大小为2×2,步幅为2,池化后通道数不变,得到的特征图大小为5×5。
上述步骤结束之后应该现有一个flatten操作,将特征图展平,大小为16×5×5=400。相当于第一个全连接的W大小为400×120,然后得到的结果维数就是120,同理第二个全连接的W大小为120×84。
下面进行三个全连接操作,前两个全连接层操作后都有sigmoid操作,由于用的是数字为例,所以最后的输出维数为10,表示分属各个类别的分数。
可以使用pytorch查看每次操作后的特征图大小,其中第一个参数指batch大小,第二个参数是通道大小,后面两个参数为特征图的高和宽。
AlexNet
AlexNet要比LeNet5深得多,两个网络结构的对比如下,左边是LeNet5,右边是AlexNet,包含了5个卷积层和三个全连接层,且激活函数使用的是ReLU。
每层的输出大小如下图所示,计算方式都类似,这里计算第一次卷积后的大小,(224-11+4)/4=227/4,向下取整得54,所以特征图大小为54×54,池化层窗口为3×3,步幅为2,池化后大小为(54-3)/2+1=26,向下取整,后面的就不赘述了。
VGG
VGG网络由若干个VGG块组成,不同的VGG模型可通过每个块中卷积层数量和输出通道数量的差异来定义,使用块可以有效地设计复杂的网络。
以单通道224×224的张量输入为例,有5个VGG块,卷积层数量和输出通道大小分别为(1, 64), (1, 128), (2, 256), (2, 512), (2, 512),其中卷积核大小均为3×3,池化层窗口大小为2×2,步幅为2,经过第一个VGG块,卷积操作得到的高和宽为224-3+2+1=224,池化后为(224-2)/2+1=112,通道数为64,下个VGG块的输入通道为也为64,输出通道为128,后面都类似。(每次卷积后都有ReLU操作然后再池化)
NiN
NiN块以一个普通卷积层开始,后面是两个1×1的卷积层,充当带有ReLU激活函数的逐像素全连接层。NiN使用卷积核形状为11×11、5×5、3×3的卷积层,每个NiN块后有一个最大池化层,池化窗口大小为3×3,步幅为2。NiN完全取消了全连接层,使用一个NiN块,其输出通道数等于标签类别的数量,最后放一个全局平均汇聚层。
以单通道224×224的张量输入为例,按照上图的NiN网络,经过第一个NiN块时,第一个卷积层卷积后,得到的高和宽为(224-11+4)/4=54(向下取整),通道数为96,经过两个1×1卷积层,大小不变。
GoogLeNet
在GoogLeNet中,基本的卷积块被称为Inception块,Inception块由四条并行路径组成,如下图所示,
GoogLeNet一共使用9个Inception块和全局平均汇聚层的堆叠来生成其估计值,Inception块之间的最大汇聚层可降低维度。
可以将上图分为六个模块,如下图所示。
假设输入是单通道96×96的张量,
第一个模块使用64通道,7×7的卷积层,填充为3,步幅为2,卷积后特征图大小为(96-7+6+2)/2=48,通道数为64,池化层窗口大小为3×3,填充1,步幅2,池化后高和宽均为(48-3+2)/2+1=24,所以第一个模块的输出是64通道,24×24的特征图。
第二个模块使用两个卷积层,第一个卷积层为64通道1×1卷积,第二个卷积层为192通道3×3卷积,填充1,步幅1,卷积后小大为24-3+2=23,通道数为192,池化层窗口大小为3×3,填充1,步幅2,池化后高和宽均为(23-3+2)/2+1=12,所以第二个模块的输出是192通道,12×12的特征图。
第三个模块包含两个Inception块,对照下面的框架图和代码,
第一个Inception块输入通道为192,c1~c4分别为64, (96, 128), (16, 32), 32。
第一条路径是1×1卷积,输出为64通道,12×12。
第二条路径先是1×1卷积,通道为96,然后是3×3卷积,填充1,通道为128,最后输出的高和宽分别为12-3+2+1=12,通道为128。
第三条路径先是1×1卷积,通道为16,然后是5×5卷积,填充2,通道为32,最后输出的高和宽分别为12-5+4+1=12,通道为32。
第四条路径先是3×3池化,填充1,然后是1×1卷积,通道为32,最后输出的高和宽分别为12-3+2+1=12,通道为32。
然后将四条路径的通道合并就是64+128+32+32=256个通道,作为下个Inception块的输入通道。
第二个Inception块输入通道为256,c1~c4分别为128, (128, 192), (32, 96), 64),过程与上面一样,就不再赘述了。经过池化后,第三个模块的最终输出为6×6,通道数为480.
第四个模块更复杂,包含5个Inception块,每个Inception块的通道参数分别如下,
Inception(480, 192, (96, 208), (16, 48), 64),
Inception(512, 160, (112, 224), (24, 64), 64),
Inception(512, 128, (128, 256), (24, 64), 64),
Inception(512, 112, (144, 288), (32, 64), 64),
Inception(528, 256, (160, 320), (32, 128), 128),
过程和上面类似,池化后最终的输出为3×3,832通道。
第五个模块包含2个Inception块,参数分别为Inception(832, 256, (160, 320), (32, 128), 128),Inception(832, 384, (192, 384), (48, 128), 128),然后使用全局平均汇聚层,将每个通道的高和宽变成1,再加一个flatten操作,最终的输出为1×1,1024个通道。
第六个模块就是一个全连接层,使得输出个数为标签类别数。
批量规范化
批量规范化可以持续加速深层网络的收敛速度,具体的可以直接看这个批量规范化
ResNet
残差网络的核心思想是:每个附加层都应该更容易地包含原始函数作为其元素之一。残差快可分为包含以及不包含1×1卷积层的残差块。
ResNet-18架构如下所示。
具体的定义和参数设置如下,我就不一一计算了有点麻烦。
DenseNet
稠密网络主要由2部分构成:稠密块(dense block)和过渡层(transition layer)。前者定义如何连接输入和输出,而后者则控制通道数量,使其不会太复杂。
一个稠密块由多个卷积块组成,每个卷积块使用相同数量的输出通道。 然而,在前向传播中,我们将每个卷积块的输入和输出在通道维上连结。
由于每个稠密块都会带来通道数的增加,使用过多则会过于复杂化模型。 而过渡层可以用来控制模型复杂度。
DenseNet首先使用同ResNet一样的单卷积层和最大汇聚层。
DenseNet使用4个稠密块,每个稠密块设置为使用4个卷积层,卷积层通道数设置为32,每个稠密块会增加4×32=128个通道。