1.卷积神经网络解决的问题
我们构造了⼀个含单隐藏层的多层感知机模型来对Fashion-MNIST数据集中的图像进⾏分类。每张图像⾼和宽均是28像素。我们将图像中的像素逐⾏展开,得到⻓度为784的向量,并输⼊进全连接层中。然而,这种分类⽅法有⼀定的局限性。
图像在同⼀列邻近的像素在这个向量中可能相距较远。它们构成的模式可能难以被模型识别。
对于大尺寸的输⼊图像,使⽤全连接层容易造成模型过大。假设输⼊是⾼和宽均为1000像素的彩⾊照⽚(含3个通 道)。即使全连接层输出个数仍是256,该层权重参数的形状是3, 000, 000 × 256:它占⽤了⼤约3 GB的内存或显存。这带来过复杂的模型和过⾼的存储开销。
卷积层尝试解决这两个问题。一方面,卷积层保留输⼊形状,使图像的像素在⾼和宽两个方向上的相关性均可能被有效识别;另一方面,卷积层通过滑动窗口将同⼀卷积核与不同位置的输⼊重复计算,从而避免参数尺⼨过大。
LeNet分为卷积层块和全连接层块两个部分。下⾯我们分别介绍这两个模块。
卷积层块⾥的基本单位是卷积层后接最⼤池化层:卷积层⽤来识别图像⾥的空间模式,如线条和物体局部,之后的最⼤池化层则⽤来降低卷积层对位置的敏感性。卷积层块由两个这样的基本单位重复堆叠构成。在卷积层块中,每个卷积层都使⽤5 × 5的窗口,并在输出上使⽤sigmoid激活函数。第⼀个卷积层输出通道数为6,第⼆个卷积层输出通道数则增加到16。这是因为第⼆个卷
积层⽐第⼀个卷积层的输⼊的⾼和宽要小,所以增加输出通道使两个卷积层的参数尺⼨类似。卷积层块的两个最⼤池化层的窗口形状均为2 × 2,且步幅为2。由于池化窗口与步幅形状相同,池化窗口在输⼊上每次滑动所覆盖的区域互不重叠。卷积层块的输出形状为(批量⼤小, 通道, ⾼, 宽)。当卷积层块的输出传⼊全连接层块时,全连接层块会将小批量中每个样本变平(flatten) 。也就是说,全连接层的输⼊形状将变成⼆维,其中第⼀维是小批量中的样本,第⼆维是每个样本变平后的向量表⽰,且向量⻓度为通道、⾼和宽的乘积。全连接层块含3个全连接层。它们的输出个数分别是120、84和10,其中10为输出的类别个数。
2.2 AlexNet
2012年,AlexNet横空出世。这个模型的名字来源于论⽂第⼀作者的姓名Alex Krizhevsky [1]。AlexNet使⽤了8层卷积神经⽹络,并以很⼤的优势赢得了ImageNet 2012图像识别挑战赛。它⾸次证明了学习到的特征可以超越⼿⼯设计的特征,从而⼀举打破计算机视觉研究的前状。
AlexNet与LeNet的设计理念⾮常相似,但也有显著的区别。
第⼀,与相对较小的LeNet相⽐,AlexNet包含8层变换,其中有5层卷积和2层全连接隐藏层,以及1个全连接输出层。下⾯我们来详细描述这些层的设计。AlexNet第⼀层中的卷积窗口形状是11 × 11。因为ImageNet中绝⼤多数图像的⾼和宽均⽐MNIST图像的⾼和宽⼤10倍以上,ImageNet图像的物体占⽤更多的像素,所以需要更⼤的卷积窗口来捕获物体。第⼆层中的卷积窗口形状减小到5 × 5,之后全采⽤3 × 3。此外,第⼀、第⼆和第五个卷积层之后都使⽤了窗口形状为3 × 3、步幅为2的最⼤池化层。而且,AlexNet使⽤的卷积通道数也⼤于LeNet中的卷积通道数数⼗倍。
紧接着最后⼀个卷积层的是两个输出个数为4096的全连接层。这两个巨⼤的全连接层带来将近1GB的模型参数。由于早期显存的限制,最早的AlexNet使⽤双数据流的设计使⼀个GPU只需要处理⼀半模型。幸运的是,显存在过去⼏年得到了长足的发展,因此通常我们不再需要这样的特别设计了。
第⼆,AlexNet将sigmoid激活函数改成了更加简单的ReLU激活函数。⼀⽅⾯,ReLU激活函数的计算更简单,例如它并没有sigmoid激活函数中的求幂运算。另⼀⽅⾯,ReLU激活函数在不同的参数初始化⽅法下使模型更容易训练。这是由于当sigmoid激活函数输出极接近0或1时,这些区域的梯度⼏乎为0,从而造成反向传播⽆法继续更新部分模型参数;而ReLU激活函数在正区间的梯度恒为1。因此,若模型参数初始化不当,sigmoid函数可能在正区间得到⼏乎为0的梯度,从而令模型⽆法得到有效训练。
第三,AlexNet通过丢弃法来控制全连接层的模型复杂度。而LeNet并没有使⽤丢弃法。
第四,AlexNet引⼊了⼤量的图像增⼴,如翻转、裁剪和颜⾊变化,从而进⼀步扩⼤数据集来缓解过拟合。
2.3 VGG
2.3.1 VGG块
VGG块的组成规律是:连续使⽤数个相同的填充为1、窗口形状为3 × 3的卷积层后接上⼀个步幅为2、窗口形状为2 × 2的最⼤池化层。卷积层保持输⼊的⾼和宽不变,而池化层则对其减半。
2.3.2 VGG网络
与AlexNet和LeNet⼀样,VGG⽹络由卷积层模块后接全连接层模块构成。卷积层模块串联数个vgg_block,其超参数由变量conv_arch定义。该变量指定了每个VGG块⾥卷积层个数和输出通道数。全连接模块则跟AlexNet中的⼀样。现在我们构造⼀个VGG⽹络。它有5个卷积块,前2块使⽤单卷积层,而后3块使⽤双卷积层。第⼀块的输出通道是64,之后每次对输出通道数翻倍,直到变为512。因为这个⽹络使⽤了8个卷积层和3个全连接层,所以经常被称为VGG-11。
2.4 NiN
2.4.1 Nin块
我们知道, 卷积层的输⼊和输出通常是四维数组 (样本, 通道, ⾼, 宽) , 而全连接层的输⼊和输出则通常是⼆维数组 (样本, 特征) 。 如果想在全连接层后再接上卷积层, 则需要将全连接层的输出变换为四维。 回忆在 “多输⼊通道和多输出通道” ⼀节⾥介绍的1×1卷积层。 它可以看成全连接层, 其中空间维度 (⾼和宽) 上的每个元素相当于样本, 通道相当于特征。 因此, NiN使⽤1×1卷积层来替代全连接层, 从而使空间信息能够⾃然传递到后⾯的层中去。 下图对⽐了NiN同AlexNet和VGG等⽹络在结构上的主要区别。
2.4.2 Nin网络
NiN是在AlexNet问世不久后提出的。它们的卷积层设定有类似之处。NiN使⽤卷积窗口形状分别为11 × 11、5 × 5和3 × 3的卷积层,相应的输出通道数也与AlexNet中的⼀致。每个NiN块后接⼀个步幅为2、窗口形状为3 × 3的最⼤池化层。
除使⽤NiN块以外,NiN还有⼀个设计与AlexNet显著不同:NiN去掉了AlexNet最后的3个全连接层,取而代之地,NiN使⽤了输出通道数等于标签类别数的NiN块,然后使⽤全局平均池化层对每个通道中所有元素求平均并直接⽤于分类。 这⾥的全局平均池化层即窗口形状等于输⼊空间维形状的平均池化层。NiN的这个设计的好处是可以显著减小模型参数尺⼨,从而缓解过拟合。然而,该设计有时会造成获得有效模型的训练时间的增加。
2.5 GooLeNet
在2014年的ImageNet图像识别挑战赛中,⼀个名叫GoogLeNet的⽹络结构⼤放异彩 。它虽然在名字上向LeNet致敬,但在⽹络结构上已经很难看到LeNet的影⼦。GoogLeNet吸收了NiN中⽹络串联⽹络的思想,并在此基础上做了很大改进。
2.5.1 Inception块
GoogLeNet中的基础卷积块叫作Inception块,得名于同名电影《盗梦空间》 (Inception) 。与上⼀节介绍的NiN块相⽐,这个基础块在结构上更加复杂,如图所示:
Inception块⾥有4条并⾏的线路。前3条线路使⽤窗口⼤小分别是1 × 1、3 ×3和5 × 5的卷积层来抽取不同空间尺⼨下的信息,其中中间2个线路会对输⼊先做1 × 1卷积来减少输⼊通道数,以降低模型复杂度。第四条线路则使⽤3 × 3最⼤池化层,后接1 × 1卷积层来改变通道数。4条线路都使⽤了合适的填充来使输⼊与输出的⾼和宽⼀致。最后我们将每条线路的输出在通道维上连结,并输⼊接下来的层中去。
2.5.2 GoogLeNet网络
GoogLeNet跟VGG⼀样, 在主体卷积部分中使⽤5个模块 (block) , 每个模块之间使⽤步幅为2的3×3最⼤池化层来减小输出⾼宽。
第⼀模块使⽤⼀个64通道的7 × 7卷积层。
第⼆模块使⽤2个卷积层:⾸先是64通道的1 × 1卷积层, 然后是将通道增⼤3倍的3 × 3卷积层。它对应Inception块中的第⼆条线路。
第三模块串联2个完整的Inception块。 第⼀个Inception块的输出通道数为64+128+32+32 = 256,其中4条线路的输出通道数⽐例为64 : 128 : 32 : 32 = 2 : 4 : 1 : 1。 其中第⼆、 第三条线路先分别将输⼊通道数减小⾄96/192 = 1/2和16/192 = 1/12后,再接上第⼆层卷积层。第⼆个Inception块输出通道数增⾄128 + 192 + 96 + 64 = 480,每条线路的输出通道数之⽐为128 : 192 : 96 : 64 =4 : 6 : 3 : 2。其中第⼆、第三条线路先分别将输⼊通道数减小⾄128/256 = 1/2和32/256 = 1/8。
第四模块更加复杂。它串联了5个Inception块,其输出通道数分别是192 + 208 + 48 + 64 = 512、160+224+64+64 = 512、128+256+64+64 = 512、 112+288+64+64 = 528和256+320+128+128 =832。这些线路的通道数分配和第三模块中的类似,⾸先含3 × 3卷积层的第⼆条线路输出最多通道, 其次是仅含1 × 1卷积层的第⼀条线路, 之后是含5 × 5卷积层的第三条线路和含3 × 3最⼤池化层的第四条线路。 其中第⼆、 第三条线路都会先按⽐例减小通道数。 这些⽐例在各个Inception块中都略有不同。
第五模块有输出通道数为256 + 320 + 128 + 128 = 832和384 + 384 + 128 + 128 = 1024的两个Inception块。 其中每条线路的通道数的分配思路和第三、 第四模块中的⼀致, 只是在具体数值上有所不同。需要注意的是,第五模块的后⾯紧跟输出层,该模块同NiN⼀样使⽤全局平均池化层来将每个通道的⾼和宽变成1。最后我们将输出变成⼆维数组后接上⼀个输出个数为标签类别数的全连接层。GoogLeNet模型的计算复杂,而且不如VGG那样便于修改通道数。
2.6 ResNet
理论上,原模型解的空间只是新模型解的空间的⼦空间。也就是说,如果我们能将新添加的层训练成恒等映射f(x) = x,新模型和原模型将同样有效。由于新模型可能得出更优的解来拟合训练数据集,因此添加层似乎更容易降低训练误差。然而在实践中,添加过多的层后训练误差往往不降反升。即使利⽤批量归⼀化带来的数值稳定性使训练深层模型更加容易,该问题仍然存在。 针对这⼀问题, 何恺明等⼈提出了残差⽹络(ResNet)。 它在2015年的ImageNet图像识别挑战赛夺魁,并深刻影响了后来的深度神经⽹络的设计。
2.6.1 残差块
让我们聚焦于神经⽹络局部。如图所⽰,设输⼊为x。假设我们希望学出的理想映射为f(x),从而作为图上⽅激活函数的输⼊。左图虚线框中的部分需要直接拟合出该映射f(x),而右图虚线框中的部分则需要拟合出有关恒等映射的残差映射f(x) − x。残差映射在实际中往往更容易优化。以本节开头提到的恒等映射作为我们希望学出的理想映射f(x)。我们只需将图中右图虚线框内上⽅的加权运算(如仿射)的权重和偏差参数学成0,那么f(x)即为恒等映射。实际中,当理想映射f(x)极接近于恒等映射时,残差映射也易于捕捉恒等映射的细微波动。右图也是ResNet的基础块,即残差块(residual block) 。在残差块中,输⼊可通过跨层的数据线路更快地向前传播。
ResNet沿⽤了VGG全3 × 3卷积层的设计。残差块⾥⾸先有2个有相同输出通道数的3 × 3卷积层。每个卷积层后接⼀个批量归⼀化层和ReLU激活函数。然后我们将输⼊跳过这两个卷积运算后直接加在最后的ReLU激活函数前。这样的设计要求两个卷积层的输出与输⼊形状⼀样,从而可以相加。如果想改变通道数, 就需要引⼊⼀个额外的1 × 1卷积层来将输⼊变换成需要的形状后再做相加运算。
2.6.2 残差网络
ResNet的前两层跟之前介绍的GoogLeNet中的⼀样:在输出通道数为64、步幅为2的7 × 7卷积层后接步幅为2的3 × 3的最⼤池化层。不同之处在于ResNet每个卷积层后增加的批量归⼀化层。GoogLeNet在后⾯接了4个由Inception块组成的模块。 ResNet则使⽤4个由残差块组成的模块, 每个模块使⽤若⼲个同样输出通道数的残差块。第⼀个模块的通道数同输⼊通道数⼀致。由于之前已经使⽤了步幅为2的最⼤池化层,所以⽆须减小⾼和宽。之后的每个模块在第⼀个残差块⾥将上⼀个模块的通道数翻倍,并将⾼和宽减半。
2.7 DenseNet
ResNet中的跨层连接设计引申出了数个后续⼯作。本节我们介绍其中的⼀个:稠密连接⽹络(DenseNet)。它与ResNet的主要区别如图所⽰。
图中将部分前后相邻的运算抽象为模块A和模块B。与ResNet的主要区别在于,DenseNet⾥模块B的输出不是像ResNet那样和模块A的输出相加,而是在通道维上连结。这样模块A的输出可以直接传⼊模块B后⾯的层。在这个设计⾥,模块A直接跟模块B后⾯的所有层连接在了⼀起。这也是它被称为“稠密连接”的原因。
DenseNet的主要构建模块是稠密块(dense block)和过渡层(transition layer) 。前者定义了输⼊和输出是如何连结的,后者则⽤来控制通道数,使之不过⼤。