深度学习模型之CNN(十七)EfficientNet网络详解
原论文:EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks
前言
在之前的学习的网络结构(例如AlexNet,VGG,ResNet等)中,都将输入图像分辨率固定为224,为什么卷积的个数要设置为这个值,为什么网络的深度设为这么深?这些问题你要问设计作者的话,估计回复就四个字——工程经验。
而这篇论文同时探索输入分辨率、网络的深度、宽度对准确率的影响。在论文中提到,本文提出的EfficientNet-B7在Imagenet top-1上达到了当年最高准确率84.3%,与之前准确率最高的GPipe相比,参数数量(Params)仅为其1/8.4,推理速度提升了6.1倍(看上去又快又轻量,但个人实际使用起来发现很吃显存)。下图是EfficientNet与其他网络的对比(注意:参数数量少并不意味推理速度就快)。
论文思想
- 下图(a)是传统的卷积神经网络;
- 下图(b)是在(a)的基础上增大了网络的宽度width,实际上指的是特征矩阵的channel。即增加卷积核的个数(增加特征矩阵的
channels
)来提升网络的性能; - 下图(c)是在(a)的基础上增大了网络的深度channel,实际上指的是通过增加网络的深度
layers
。即使用更多的层结构来提升网络的性能; - 下图(d)是在(a)的基础上通过增加输入
网络的分辨率
来提升网络的性能; - 本篇论文中同时增加网络的
width
、channel
以及输入网络的分辨率来提升网络的性能,如图(e)
- 增加网络的
width
,即增加卷积核的个数,能够获得更高细粒度的特征并且也更容易训练,但对于width很大而深度较浅的网络往往很难学习到更深层次的特征。 - 根据以往的经验,增加网络的深度
depth
,即增加网络的层结构,能够得到更加丰富、复杂的特征并且能够很好的应用到其它任务中。但网络的深度过深会面临梯度消失,训练困难的问题。 - 增加输入网络的图像分辨率能够潜在得获得更高细粒度的特征模板,但对于非常高的输入分辨率,准确率的增益也会减小。并且大分辨率图像会增加计算量。
EfficientNet的网络结构
通过网络搜索(Neural Architecture Search)技术得到的结构(B1-B7就是在B0的基础上修改Resolution
,Channels
以及Layers
),整个网络框架由一系列Stage组成。表中的卷积层后都默认跟有BN以及Swish激活函数,MBConv为MobileNet Conv。
Resolution
:每一层Stage输入特征矩阵的高和宽;Channels
:通过该Stage后输出特征矩阵的Channels;Layers
:指将Operator操作重复多少次stride
:指的是每一层Stage的第一个MBConv中卷积核的stride,其余默认stride = 1
网络总共分成了9个Stage,第一个Stage是一个卷积核大小为3x3步距为2的普通卷积层(包含BN和激活函数Swish),Stage2~Stage8都是在重复堆叠MBConv结构,而Stage9由一个普通的1x1的卷积层(包含BN和激活函数Swish)、一个平均池化层和一个全连接层组成。
表格中每个MBConv后会跟一个数字1或6,这里的1或6就是倍率因子n即MBConv中第一个1x1的卷积层会将输入特征矩阵的channels扩充为n倍,其中k3x3或k5x5表示MBConv中Depthwise Conv所采用的卷积核大小。
MBConv结构
MBConv其实就是MobileNetV3网络中的InvertedResidualBlock,但也有些许区别。一个是采用的激活函数不一样(EfficientNet的MBConv中使用的都是Swish激活函数),另一个是在每个MBConv中都加入了SE(Squeeze-and-Excitation)模块。
如下图所示,MBConv结构主要由一个1x1的普通卷积(升维作用,包含BN和Swish),一个kxk的Depthwise Conv卷积(包含BN和Swish)k的具体值可看EfficientNet-B0的网络框架主要有3x3和5x5两种情况,一个SE模块,一个1x1的普通卷积(降维作用,包含BN),一个Droupout层构成。搭建过程中还需要注意几点:
- 第一个升维的1x1卷积层,它的卷积核个数是输入特征矩阵channel的n倍,n ∈ { 1 , 6 }。
- 当n = 1时,不要第一个升维的1x1卷积层,即Stage2中的MBConv结构都没有第一个升维的1x1卷积层(这和MobileNetV3网络类似)。
- 关于shortcut连接,仅当输入MBConv结构的特征矩阵与输出的特征矩阵shape相同时才存在(代码中可通过stride==1 and inputc_channels==output_channels条件来判断)。
注意:在源码实现中只有使用shortcut的时候才有Dropout层
SE模块如下图所示,由一个全局平均池化,两个全连接层组成。第一个全连接层的节点个数是输入该MBConv特征矩阵channels的1/4,且使用Swish激活函数。第二个全连接层的节点个数等于Depthwise Conv
层输出的特征矩阵channels
,且使用Sigmoid激活函数。
EfficientNet-B0-B7参数
input_size
代表训练网络时输入网络的图像大小width coeficient
:代表channel维度上的倍率因子,比如在 EfcientNetB0中Stagel的3x3卷积层所使用的卷积核个数是32,那么在B6中就是 32 X 18=57.6接着取整到离它最近的8的整数倍即56,其它Stage同理。depth coeficient
:代表depth维度上的倍率因子(仅针对Stage2到Stage8),比如在EcientNetB0中Stage7的L=4,那么在B6中就是 4 X 2.6=10.4,接着向上取整即11。drop_connect_rate
是在MBConv
结构中dropout层使用的drop_rate
,在官方keras模块的实现中MBConv
结构的drop_rate
是从0递增到drop_connect_rate
的(在源码实现中只有使用shortcut的时候才有Dropout层)。还需要注意的是,这里的Dropout层是Stochastic Depth
,即会随机丢掉整个block的主分支(只剩捷径分支,相当于直接跳过了这个block)也可以理解为减少了网络的深度。dropout_rate
是最后一个全连接层前的dropout
层(在stage9
的Pooling与FC之间)的dropout_rate
。
Model | input_size | width_coefficient | depth_coefficient | dropout_connect_rate | dropout_rate |
---|---|---|---|---|---|
EfficientNetB0 | 224x224 | 1.0 | 1.0 | 0.2 | 0.2 |
EfficientNetB1 | 240x240 | 1.0 | 1.1 | 0.2 | 0.2 |
EfficientNetB2 | 260x260 | 1.1 | 1.2 | 0.2 | 0.3 |
EfficientNetB3 | 300x300 | 1.2 | 1.4 | 0.2 | 0.3 |
EfficientNetB4 | 380x380 | 1.4 | 1.8 | 0.2 | 0.4 |
EfficientNetB5 | 456x456 | 1.6 | 2.2 | 0.2 | 0.4 |
EfficientNetB6 | 528x528 | 1.8 | 2.6 | 0.2 | 0.5 |
EfficientNetB7 | 600x600 | 2.0 | 3.1 | 0.2 | 0.5 |
EfficientNet与当时主流网络的性能参数对比
虽然参数少,准确率高,但是超级占显存。