原论文名称:EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks
论文下载地址:https://arxiv.org/abs/1905.11946
原论文提供代码:https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet
自己使用Pytorch实现的代码: pytorch_classification/Test9_efficientNet
自己使用Tensorflow实现的代码: tensorflow_classification/Test9_efficientNet
不想看文章的可以看下我在bilibili上录制的视频:https://www.bilibili.com/video/BV1XK4y1U7PX
在之前的一些手工设计网络中(AlexNet,VGG,ResNet等等)经常有人问,为什么输入图像分辨率要固定为224,为什么卷积的个数要设置为这个值,为什么网络的深度设为这么深?这些问题你要问设计作者的话,估计回复就四个字——工程经验。而这篇论文主要是用NAS(Neural Architecture Search)技术来搜索网络的图像输入分辨率 r r r,网络的深度 d e p t h depth depth以及channel
的宽度 w i d t h width width三个参数的合理化配置。在之前的一些论文中,基本都是通过改变上述3个参数中的一个来提升网络的性能,而这篇论文就是同时来探索这三个参数的影响。在论文中提到,本文提出的EfficientNet-B7在Imagenet top-1上达到了当年最高准确率84.3%,与之前准确率最高的GPipe相比,参数数量(Params)仅为其1/8.4,推理速度提升了6.1倍(看上去又快又轻量,但个人实际使用起来发现很吃显存)。下图是EfficientNet与其他网络的对比(注意,参数数量少并不意味推理速度就快)。
在之前的一些论文中,有的会通过增加网络的width
即增加卷积核的个数(增加特征矩阵的channels
)来提升网络的性能如图(b)所示,有的会通过增加网络的深度即使用更多的层结构来提升网络的性能如图(c)所示,有的会通过增加输入网络的分辨率来提升网络的性能如图(d)所示。而在本篇论文中会同时增加网络的width
、网络的深度以及输入网络的分辨率来提升网络的性能如图(e)所示:
depth
能够得到更加丰富、复杂的特征并且能够很好的应用到其它任务中。但网络的深度过深会面临梯度消失,训练困难的问题。The intuition is that deeper ConvNet can capture richer and more complex features, and generalize well on new tasks. However, deeper networks are also more difficult to train due to the vanishing gradient problem
width
能够获得更高细粒度的特征并且也更容易训练,但对于width
很大而深度较浅的网络往往很难学习到更深层次的特征。wider networks tend to be able to capture more fine-grained features and are easier to train. However, extremely wide but shallow networks tend to have difficulties in capturing higher level features.
With higher resolution input images, ConvNets can potentially capture more fine-grained patterns. but the accuracy gain diminishes for very high resolutions.
下图展示了在基准EfficientNetB-0上分别增加width
、depth
以及resolution
后得到的统计结果。通过下图可以看出大概在Accuracy达到80%时就趋于饱和了。
接着作者又做了一个实验,采用不同的 d , r d, r d,r组合,然后不断改变网络的width
就得到了如下图所示的4条曲线,通过分析可以发现在相同的FLOPs下,同时增加 d d d和 r r r的效果最好。
为了方便后续理解,我们先看下论文中通过 NAS(Neural Architecture Search) 技术搜索得到的EfficientNetB0的结构,如下图所示,整个网络框架由一系列Stage
组成, F ^ i \widehat{F}_i F
i表示对应Stage
的运算操作, L ^ i \widehat{L}_i L
i表示在该Stage
中重复 F ^ i \widehat{F}_i F
i的次数:
作者在论文中对整个网络的运算进行抽象:
N ( d , w , r ) = ⊙ i = 1... s F i L i ( X ⟨ H i , W i , C i ⟩ ) N(d,w,r)=\underset{i=1...s}{\odot} {F}_i^{L_i}(X_{\left\langle{
{H}_i, {W}_i, {C}_i } \right\rangle}) N(d,w,r)=i=1...s⊙FiLi(X⟨Hi,Wi,Ci⟩)
其中:
Operator
),那么 F i L i {F}_i^{L_i} FiLi表示在 S t a g e i {\rm Stage}i Stagei中 F i {F}_i Fi运算被重复执行 L i L_i Li次。input tensor
)。shape
)。为了探究 d , r , w d, r, w d,r,w这三个因子对最终准确率的影响,则将 d , r , w d, r, w d,r,w加入到公式中,我们可以得到抽象化后的优化问题(在指定资源限制下),其中 s . t . s.t. s.t.代表限制条件:
Our target is to maximize the model accuracy for any given resource constraints, which can be formulated as an optimization problem:
m a x d , w , r A c c u r a c y ( N ( d , w , r ) ) s . t . N ( d , w , r ) = ⊙ i = 1... s F ^ i d ⋅ L ^ i ( X ⟨ r ⋅ H ^ i , r ⋅ W ^ i , w ⋅ C ^ i ⟩ ) M e m o r y ( N ) ≤ t a r g e t _ m e m o r y F L O P s ( N ) ≤ t a r g e t _ f l o p s ( 2 ) \underset{d, w, r}{max} \ \ \ \ \ Accuracy(N(d, w, r)) \\ s.t. \ \ \ \ N(d,w,r)=\underset{i=1...s}{\odot} \widehat{F}_i^{d \cdot \widehat{L}_i}(X_{\left\langle{r \cdot \widehat{H}_i, \ r \cdot \widehat{W}_i, \ w \cdot \widehat{C}_i } \right\rangle}) \\ Memory(N) \leq {\rm target\_memory} \\ \ \ \ \ \ \ \ \ \ \ FLOPs(N) \leq {\rm target\_flops} \ \ \ \ \ \ \ \ (2) d,w,rmax Accuracy(N(d,w,r))s.t. N(d,w,r)=i=1...s⊙F
id⋅L
i(X⟨r⋅H
i, r⋅W
i, w⋅C
i⟩)Memory(N)≤target_memory FLOPs(N)≤target_flops (2)
其中:
channel
即 C ^ i \widehat{C}_i Ctarget_memory
为memory
限制target_flops
为FLOPs限制接着作者又提出了一个混合缩放方法 ( compound scaling method) 在这个方法中使用了一个混合因子 ϕ \phi ϕ去统一的缩放width,depth,resolution
参数,具体的计算公式如下,其中 s . t . s.t. s.t.代表限制条件:
d e p t h : d = α ϕ w i d t h : w = β ϕ r e s o l u t i o n : r = γ ϕ ( 3 ) s . t . α ⋅ β 2 ⋅ γ 2 ≈ 2 α ≥ 1 , β ≥ 1 , γ ≥ 1 depth: d={\alpha}^{\phi} \\ width: w={\beta}^{\phi} \\ \ \ \ \ \ \ resolution: r={\gamma}^{\phi} \ \ \ \ \ \ \ \ \ \ (3) \\ s.t. \ \ \ \ \ \ \ {\alpha} \cdot {\beta}^{2} \cdot {\gamma}^{2} \approx 2 \\ \alpha \geq 1, \beta \geq 1, \gamma \geq 1 \ \ \ \ \ \ depth:d=αϕwidth:w=βϕ resolution:r=γϕ (3)s.t. α⋅β2⋅γ2≈2α≥1,β≥1,γ≥1
注意:
depth
的关系是:当depth
翻倍,FLOPs也翻倍。width
的关系是:当width
翻倍(即channal
翻倍),FLOPs会翻4倍,因为卷积层的FLOPs约等于 f e a t u r e w × f e a t u r e h × f e a t u r e c × k e r n e l w × k e r n e l h × k e r n e l n u m b e r feature_w \times feature_h \times feature_c \times kernel_w \times kernel_h \times kernel_{number} featurew×featureh×featurec×kernelw×kernelh×kernelnumber(假设输入输出特征矩阵的高宽不变),当width
翻倍,输入特征矩阵的channels( f e a t u r e c feature_c featurec)和输出特征矩阵的channels或卷积核的个数( k e r n e l n u m b e r kernel_{number} kernelnumber)都会翻倍,所以FLOPs会翻4倍resolution
的关系是:当resolution
翻倍,FLOPs也会翻4倍,和上面类似因为特征矩阵的宽度 f e a t u r e w feature_w featurew和特征矩阵的高度 f e a t u r e h feature_h featureh都会翻倍。所以总的FLOPs倍率可以用近似用 ( α ⋅ β 2 ⋅ γ 2 ) ϕ (\alpha \cdot \beta^{2} \cdot \gamma^{2})^{\phi} (α⋅β2⋅γ2)ϕ来表示,当限制 α ⋅ β 2 ⋅ γ 2 ≈ 2 \alpha \cdot \beta^{2} \cdot \gamma^{2} \approx 2 α⋅β2⋅γ2≈2时,对于任意一个 ϕ \phi ϕ而言FLOPs相当增加了 2 ϕ 2^{\phi} 2ϕ倍。
接下来作者在基准网络EfficientNetB-0(在后面的网络详细结构章节会详细讲)上使用NAS来搜索 α , β , γ \alpha, \beta, \gamma α,β,γ这三个参数。
需要注意的是,对于不同的基准网络搜索出的 α , β , γ \alpha, \beta, \gamma α,β,γ也不定相同。还需要注意的是,在原论文中,作者也说了,如果直接在大模型上去搜索 α , β , γ \alpha, \beta, \gamma α,β,γ可能获得更好的结果,但是在较大的模型中搜索成本太大(Google大厂居然说这种话),所以这篇文章就在比较小的EfficientNetB-0模型上进行搜索的。
Notably, it is possible to achieve even better performance by searching for α, β, γ directly around a large model, but the search cost becomes prohibitively more expensive on larger models. Our method solves this issue by only doing search once on the small baseline network (step 1), and then use the same scaling coefficients for all other models (step 2).
下表为EfficientNet-B0的网络框架(B1-B7就是在B0的基础上修改Resolution
,Channels
以及Layers
),可以看出网络总共分成了9个Stage
,第一个Stage
就是一个卷积核大小为3x3
步距为2的普通卷积层(包含BN和激活函数Swish),Stage2~Stage8
都是在重复堆叠MBConv
结构(最后一列的Layers
表示该Stage
重复MBConv
结构多少次),而Stage9
由一个普通的1x1
的卷积层(包含BN和激活函数Swish)一个平均池化层和一个全连接层组成。表格中每个MBConv
后会跟一个数字1或6,这里的1或6就是倍率因子n
即MBConv
中第一个1x1
的卷积层会将输入特征矩阵的channels
扩充为n
倍,其中k3x3
或k5x5
表示MBConv
中Depthwise Conv
所采用的卷积核大小。Channels
表示通过该Stage
后输出特征矩阵的Channels
。
MBConv
其实就是MobileNetV3网络中的InvertedResidualBlock
,但也有些许区别。一个是采用的激活函数不一样(EfficientNet的MBConv
中使用的都是Swish激活函数),另一个是在每个MBConv
中都加入了SE(Squeeze-and-Excitation)模块。下图是我自己绘制的MBConv
结构。
如图所示,MBConv
结构主要由一个1x1
的普通卷积(升维作用,包含BN和Swish),一个kxk
的Depthwise Conv
卷积(包含BN和Swish)k
的具体值可看EfficientNet-B0的网络框架主要有3x3
和5x5
两种情况,一个SE
模块,一个1x1
的普通卷积(降维作用,包含BN),一个Droupout
层构成。搭建过程中还需要注意几点:
1x1
卷积层,它的卷积核个数是输入特征矩阵channel
的 n n n倍, n ∈ { 1 , 6 } n \in \left\{1, 6\right\} n∈{1x1
卷积层,即Stage2
中的MBConv
结构都没有第一个升维的1x1
卷积层(这和MobileNetV3网络类似)。shortcut
连接,仅当输入MBConv
结构的特征矩阵与输出的特征矩阵shape
相同时才存在(代码中可通过stride==1 and inputc_channels==output_channels
条件来判断)。MBConv
特征矩阵channels
的 1 4 \frac{1}{4} 41,且使用Swish激活函数。第二个全连接层的节点个数等于Depthwise Conv
层输出的特征矩阵channels
,且使用Sigmoid激活函数。dropout_rate
在tensorflow的keras源码中对应的是drop_connect_rate
后面会细讲(注意,在源码实现中只有使用shortcut的时候才有Dropout层)。还是先给出EfficientNetB0的网络结构,方便后面理解。
通过上面的内容,我们是可以搭建出EfficientNetB0网络的,其他版本的详细参数可见下表:
Model | input_size | width_coefficient | depth_coefficient | drop_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 |
input_size
代表训练网络时输入网络的图像大小width_coefficient
代表channel
维度上的倍率因子,比如在 EfficientNetB0中Stage1
的3x3
卷积层所使用的卷积核个数是32,那么在B6中就是 32 × 1.8 = 57.6 32 \times 1.8=57.6 32×1.8=57.6接着取整到离它最近的8的整数倍即56,其它Stage
同理。depth_coefficient
代表depth
维度上的倍率因子(仅针对Stage2
到Stage8
),比如在EfficientNetB0中Stage7
的 L ^ i = 4 {\widehat L}_i=4 Ldrop_connect_rate
是在MBConv
结构中dropout层使用的drop_rate
,在官方keras模块的实现中MBConv
结构的drop_rate
是从0递增到drop_connect_rate
的(具体实现可以看下官方源码,注意,在源码实现中只有使用shortcut的时候才有Dropout层)。还需要注意的是,这里的Dropout层是Stochastic Depth
,即会随机丢掉整个block的主分支(只剩捷径分支,相当于直接跳过了这个block)也可以理解为减少了网络的深度。具体可参考Deep Networks with Stochastic Depth
这篇文章。dropout_rate
是最后一个全连接层前的dropout
层(在stage9
的Pooling与FC之间)的dropout_rate
。最后给出原论文中关于EfficientNet与当时主流网络的性能参数对比: