引言
在上一篇文章cs231n 2023春季课程理解——lecture_5中,我们介绍了卷积神经网络的发展史以及卷积神经网络的总体框架以及它的重要组成部分:卷积层,池化层以及全连接层。在这篇文章中,我们主要介绍一下卷积神经网络的另外一个组成部分:归一化操作(还有一个激活函数,下一讲来讲述),并通过一些实际的卷积神经网络架构来学习卷积神经网络。
归一化(Normalization)
在讲解批归一化之前,我们先看一个问题。对于一个单层网络 y = W x y=Wx y=Wx, 在遇到以下两种情况的时候,可能会导致优化变得很困难。这两种情况分别为:
- 输入数据x不是以0为中心分布的
- 输入数据x对每个元素都有不同的比例
面对情况1,我们可以使用一个非常大的偏执项b来解决。面对情况2,我们就需要权重参数W中的元素变化很大。那么,有没有什么更好的方法来解决这些问题呢?一个想法就是,强制网络中每层的输入x能够很好的进行缩放(也就是让它符合标准的高斯分布),让其不会出现上面两种情况。
批归一化(Batch Normalization)
现在我们想象一下,现在有一些小批量的输入数据,每个输入数据x都有D维,那么如果对这个小批量数据的每个维度进行归一化,使其符合单位高斯分布,我们可以使用以下公式:
x
^
(
k
)
=
x
^
(
k
)
−
E
[
x
^
(
k
)
]
V
a
r
(
x
^
(
k
)
)
\hat{x}^{(k)} = \frac{\hat{x}^{(k)}-E[\hat{x}^{(k)}]}{\sqrt{Var(\hat{x}^{(k)})} }
x^(k)=Var(x^(k))x^(k)−E[x^(k)]这个公式其实就是随机变量转为高斯分布的公式,它是可微的,其中的均值和方差都是从整个训练集中计算出来的。具体过程如下图所示:
批归一化会把输入限制在非线性函数的线性区域,但这个约束太严格了(因为我们有时候并不想一点饱和都没有)。对此,我们可以添加两个可学习参数
γ
\gamma
γ和
β
\beta
β来控制缩放和平移,那么就有公式:
y
(
k
)
=
γ
(
k
)
x
^
(
k
)
+
β
(
k
)
y^{(k)} = \gamma^{(k)}\hat{x}^{(k)}+\beta^{(k)}
y(k)=γ(k)x^(k)+β(k)
以上的批处理归一化只能应用于训练网络模型的时候,在对网络模型进行测试的时候,批处理归一化操作变成了一个线性操作(对于均值和方差可以使用训练时得到的数据)。此外,批处理归一化一般用于全连接层或者卷积层之后,在非线性操作之前。
对数据进行批归一化处理,具有以下优点:
- 让卷积神经网络更加容易训练
- 改善梯度流(Improves gradient flow)
- 允许更高的学习率,让网络更快收敛
- 具有更好的鲁棒性(rubust): 减少对初始化的依赖
- 在训练过程中起到正则化的作用
- 测试时可以与卷积层融合
层归一化(Layer Normalization)
虽然批归一化可以让网络的训练变得更容易,但是对批量的大小(batch)非常依赖。如果批量的值太小,那么效果不好,如果批量的值太大,又会受到硬件的限制。所以它在对输入批量大小具有上限的复杂网络中效果不好。
为了解决(或者说缓解)这个问题,其他学者提出来一些替代方案,其中之一就是层归一化。在层归一化中,不在对批量进行归一化,而是对特征向量进行归一化,即层归一化是基于该特征向量内的所有项的总和来归一化对应于单个数据点。
实例归一化(Instance Normalization)与组归一化(Group Normalization)
另外两种常用的归一化方法为实例归一化(Instance Normalization)与组归一化(Group Normalization)。
与前两种归一化方法不同的是,实例归一化是在单张图片的单个通道上进行归一化操作。而组归一化则是将整张图片分成G个组,然后对每个组进行归一化操作。以上四种归一化操作的直观理解图如下。
经典卷积神经网络
现在我们知道了卷积层、池化层、全连接层、激活函数(之前有提到过,下讲讲详细介绍)以及归一化处理。那么我们该如何将它们放到一起呢?接下来我们通过一些经典卷积神经网络来回答这个问题。
AlexNet
2012年,有一只神兵从天而降,以8层深(卷积层和全连接层数量)的卷积神经网络在imagenet挑战赛上面大显身手,并获得了当年的挑战赛冠军,这是第一个基于卷积神经网络的冠军,它就是AlexNet。现在,我们通过AlexNet来了解卷积神经网络的结构。
上图展示了AlexNet以及它的结构,主要由五层卷积层,三层最大池化层,两个Norm(归一化)操作以及三层全连接层组成。对于第一层,其输入是一个227×227×3的图像,卷积核大小为11×11,stride为4,数量为96个,再进行卷积操作之后,第一层的输出的尺寸大小(高和宽)为(227-11)/4+1=55, 深度为96。这一层的参数量为(11×11×3+1)×96=35k(+1是有偏置项b,k是计量单位,1k=1024,之后的网络层的参数量可以自己仿照着计算)。第二层是一个最大池化操作(降低图像分辨率,减少此后的网络参数),池化层的大小为3×3,步长为2(之后的池化操作也是如此),因此,它的输出为27×27×96,这层中没有增加任何参数量(没有新的权重W,也就是卷积核,以及偏置项b)。之后使用了一个归一化操作,来让特征数据保持标准高斯分布,加快网络的收敛。第三层是第二个卷积层,它的卷积核大小为5×5×256(高度×宽度×卷积核数量,以后也这样显示),步长为1,此时,使用了padding操作,且padding=2,以保持输入输出大小不变,所以最终输出为27x27x256。同理,第四层使用了第二个最大池化层,并在其之后应用归一化操作,之后的输出为13x13x256。第五、第六、第七层连续使用了三次卷积操作,卷积核分别为3×3×384、3×3×384、3×3×256,并且步长为1,padding为1,这些操作之后的的输出分别为13x13x384、13x13x384、13x13x256;最后,使用了三个全连接层来进行最终的分类,这三个连接层分别有4096,4096,1000个神经元(也就是全连接层的输出,最后是1000个神经元的原因是因为有1000个类别)。
ZFNet
ZFNet是2013年ImageNet挑战赛的冠军。它修改了网络结构中的超参数来实现对 AlexNet 的改良,简单地说,就是增加了中间卷积层的尺寸,让第一层的步长和滤波器尺寸更小。具体与AlexNet的不同之处在于,第一个卷积层中,卷积核的大小由11×11变成了7×7,步长stride由4变成了2;在第3, 4, 5个卷积层中,卷积核的个数由384,384,256变成了512,1024,512。其网络结构图如下:
VGG
VGG是2014年的ImageNet挑战赛亚军(图像分类,第一是GoogLeNet),从这年开始,卷积神经网络的深度开始增加。它展示出了网络的深度是算法优良性能的关键部分。此外,它使用了更小的卷积核。与AlexNet相比,他的不同之处在于网络层深度为16或者19(两个版本),此外,它的池化操作使用的感受野为2×2,步长为2,所有卷积操作的卷积核大小为3×3(使用大小为3×3的卷积核是因为3个3×3的卷积核的感受野和一个7×7的卷积核一样大,并且参数更少,毕竟一个是3×3×3×C,而另一个是7×7×C),stride为1,padding为1。其具体结构图以及内存和参数量计算图(通过这个图我们也能看出,内存耗的更多的事最开始的卷积层,而参数量更多的是最后的全连接层)如下:
GoogLeNet
GoogLeNet是2014年的ImageNet挑战赛冠军,它有着更深的层数,同时计算更加高效(参数更少,因为自己提出的一个模块以及最后使用全局平均池化操作替代全连接层),其结构图下图。
这个网络最主要的是它提出的Inception模块(整个网络也差不多就是由它们叠加在一起的),这个模块将输入送到四个平行的操作中(这个模块有多个版本,我就随便举例了,如三个卷积层,一个池化层),在送到不同操作中之后,特征图的通道数量变少(如将256分别降成128,196,96),然后进行操作(操作之后的大小一样,如输入的图像大小为56×56,四个操作输出的大小均为28×28),之后再将输出进行拼接。但这个模块的缺点是计算变得更加复杂,因此,它们在每个平行操作之后添加了一个1×1的卷积操作来降低通道数量(也就是上图(或者下图,下图展示了两个版本的不同)的展现了,目的是降低计算的复杂度,降低参数量)。
ResNet
ResNet是2015年的挑战赛冠军,它是由何凯明等人提出的。直接让网络深度大大增加,到达了152层。其主要结构为残差模块(Residual block)。这个模块使用了跳跃连接(将底层特征连接到更深层),开创性地解决了之前的网络结构不能很深的问题(如果深了,效果反而更差,因为网络越深,优化越难)。正是因为这个小小的跳跃连接,让网络不能很深的这个问题得以解决。其网络结构如下:
由上图我们可以看出,ResNet就是由残差模块组成,且每个残差模块具有两个3×3的卷积层,并且周期性的(每隔几个残差模块)使用一个步长为2的卷积层来降低特征图的大小,当然,它在输入的开始,也使用了一个卷积层,卷积核为7×7;而在最后的输出中,除了最后用于输出的全连接层之外,没有用任何其他的全连接层。ResNet总共也有着不同的版本,不同版本深度不一样。具体有18,34,50,101和152,其中,如果网络层数大于等于50层,则会和GoogLeNet一样,在模块中使用1×1卷积层来降低通道数量。训练ResNet的参数设置如下图:
在此之后,大部分卷积神经网络都基于ResNet来改进的(至少是使用了残差模块,或者在残差模块的基础上改进的),如2016年的ImageNet挑战赛冠军就是使用ResNet和Inception模块相结合的,Inception-V4也是将残差模块与Inception模块结合。
SENet
2017年的ImageNet挑战赛冠军,在网络中使用了一个特征校准模块(也就是注意力机制,正式它让注意力机制在那几年席卷计算机视觉),让网络可以自适应地重新调整特征映射(也就是输出的特征图)的权重。它使用了一个全局平均池化层来获取全局特征,再使用两个全连接层来决定特征映射的权重。其结构图如下:
其他卷积神经网络
2017年之后,ImageNet挑战赛停止举办了(转到了Kaggle上),但是研究卷积神经网络结构的研究却没有中止。一些改进的网络(或者模块)如下:
小结
根据上面的一些经典卷积神经网络的介绍,我们知道了卷积神经网络的构造主要就是通过卷积层和池化层,在之后使用激活函数和归一化参照,以此来进行叠加使用,最后再使用一个(或几个,现在很少了)全连接层来进行最终分类(分割可能还没有全连接层)。除此之外,就是需要提出一些新的结构来构建更好的网络。
对于上面讲的网络模型,AlexNet向我们展示了使用卷积神经网络来训练计算机视觉模型;ZFNet, VGG展示了更深的网络效果能更好;GoogLeNet是一个是使用1×1卷积核来提高网络效率的模型之一,并且它使用全局平均池化来替代全连接层;ResNet教导了我们如何去训练一个非常深的网络模型(只是受限于GPU和内存,并且网络越深,它的提升越小);在ResNet之后,卷积神经网络在图像分类上的效果比人类还要好,自此大家将注意力放到如何构建一个更高效的网络模型;许多轻量级的网络(如MobileNet, ShuffleNet等)目的在于将其放在移动设备上(比如手机等)。
迁移学习
在卷积神经网络中,数据也是一个非常重要的部分。如果数据不足,也可能会导致网络过拟合,此时就可以使用迁移学习(当然我其实不是很赞同这是真正的迁移学习,我认为这可以算是迁移学习的一种应用,即在其他的大数据集上先进行一次训练,之后再对自己的小数据集进行训练)来解决这个问题。具体的流程为:
- 在一个大数据集上训练卷积神经网络,得到模型(比如使用 ImageNet,有 1000 个分类)
- 使用一个小数据集,更改最后的分类数,比如1000改为10。这时最后一个全连接层的参数矩阵变成 4096 × C(C是最终的分类数),初始化这个矩阵,重新训练这个全连接层,保持前面的所有层不变,因为前面的层已经训练好了,有了泛化能力。
- 如果数据集比较大,训练的层数可以增多,比如可以训练最后三个全连接层。同时可以使用较低的学习率微调参数。
总结
在本文中,主要向大家讲解了常见的归一化操作,并通过一些经典的卷积神经网络来学习卷积神经网络是如何进行构建的。此外,简单的介绍了一下迁移学习。
注
本文所有图片均来自于cs231公开课的网站之中。