论文地址:https://arxiv.org/pdf/1905.11946.pdf
GitHub实现地址:https://github.com/tensorflow/tpu/tree/master/models/official/efficientnet
这篇工作中的网络结构基本采用的是mobilenet的结构,关于mobilenet的详情可以查看mobilenet-v1和mobilenet-v2详解。这篇文章主要是反思了一下在一定的网络结构的情况下,是否存在某种放大卷积计算量的原则,保证网络的精度和速度达到一个很好的平衡。
一、关于网络放大的思考
这里对计算量的放大有三种方面,width(指的是网络中卷积的通道数)、depth(指的是网络的层数)、resolution(指的是网络的输入图片大小),放大上述三方面的比例因子分别用
α
、
β
、
γ
\alpha、\beta、 \gamma
α、β、γ表示。三个维度如下图所示:
上图如果不仔细看容易误解,仔细看上图最左边的图,才能很好的理解 α 、 β 、 γ \alpha、\beta、 \gamma α、β、γ所代表的维度。
结论1
对于width、depth、resolution三个方向,文章都分别的举了一些例子来说明观察到的一个结论,这个结论就是,从上述三个方面来放大网络都能是的网络的精度得到题设,但是对于大的网络来说提升的效果是有限的。
结论2
文章提到上述的三个维度不是相互独立的,从直觉上来讲,对于输入的图片分辨率更高的情况,需要有更深的网络来获得更大的感受野。同样的,对于更高分辨率的图片,需要有更多的通道来获取更精确的特征。这也说明这三个维度的的放大系数是不独立的。
这就得到了有一个结论,为了得到更高的精度,网络三个维度的放大不是独立的,有一个平衡的条件。
为了将网络的放大更为的方便,文章提出compound scaling method的概念,就是希望通过一个参数来控制网络的放大程度,这个参数用
ϕ
\phi
ϕ表示。文章规定放大网络有下列的原则:
d
e
p
t
h
:
d
=
α
ϕ
depth: d={\alpha}^{\phi}
depth:d=αϕ
w
i
d
t
h
:
w
=
β
ϕ
width: w={\beta}^{\phi}
width:w=βϕ
r
e
s
o
l
u
t
i
o
n
:
r
=
γ
ϕ
resolution: r={\gamma}^{\phi}
resolution:r=γϕ
s
.
t
.
α
⋅
β
2
⋅
γ
2
≈
2
s.t. \alpha \cdot \beta^2 \cdot \gamma^2 \approx 2
s.t.α⋅β2⋅γ2≈2
α
≥
1
,
β
≥
1
,
γ
≥
1
\alpha\ge1, \beta\ge1, \gamma\ge1
α≥1,β≥1,γ≥1
为什么depth没有平方,其余的有平方项。因为对于flops来说,depth增加一倍,计算量增加一倍,但是其余两项都是对应维度增加一倍,计算量增加4倍。至于为什么
α
⋅
β
2
⋅
γ
2
≈
2
\alpha \cdot \beta^2 \cdot \gamma^2 \approx 2
α⋅β2⋅γ2≈2,嗯,这是文章规定的。当
(
α
⋅
β
2
⋅
γ
2
)
ϕ
(\alpha \cdot \beta^2 \cdot \gamma^2)^\phi
(α⋅β2⋅γ2)ϕ时,网络计算量增加
2
ϕ
2^\phi
2ϕ。
二、网络结构
网络结构没啥可说的,文章类似MnasNet,采用nas方式搜索得到一个基本网络结构Efficientnet-B0,网络结构如下表所示:
表中Conv表示的是标注卷积,MBConv表示的是类似于mobilenet中的inverted bottleneck,不同的是mobilenet全是
3
×
3
3\times3
3×3的卷积,这里还有
5
×
5
5\times5
5×5大小的卷积,而且在bottleneck中还加入了se模块(详情查看SENet(Squeeze-and-Excitation Networks)论文详解
)。
文章通过Efficientnet-B0的网络结构和上面讲的网络放大因子的网格搜索方式得到了Efficientnet家族,称为Efficientnet-B0~Efficientnet-B7。文章做法是:
- 先固定 ϕ = 1 \phi=1 ϕ=1,调节 α ⋅ β 2 ⋅ γ 2 ≈ 2 \alpha \cdot \beta^2 \cdot \gamma^2 \approx 2 α⋅β2⋅γ2≈2,得到B0的一组好的参数, α = 1.2 , β = 1.1 , γ = 1.15 \alpha=1.2, \beta=1.1, \gamma=1.15 α=1.2,β=1.1,γ=1.15
- 固定上述得到的 α 、 β 、 γ \alpha 、\beta 、\gamma α、β、γ值,然后调节 ϕ \phi ϕ,得到Efficientnet-B1~Efficientnet-B7。
关于网络的效果,可以查看文章,下面关于实现还要多说两句。
- 对于 α 、 β 、 γ \alpha 、\beta 、\gamma α、β、γ值,代码设置如下,如下:
# (width_coefficient, depth_coefficient, resolution, dropout_rate)
'efficientnet-b0': (1.0, 1.0, 224, 0.2),
'efficientnet-b1': (1.0, 1.1, 240, 0.2),
'efficientnet-b2': (1.1, 1.2, 260, 0.3),
'efficientnet-b3': (1.2, 1.4, 300, 0.3),
'efficientnet-b4': (1.4, 1.8, 380, 0.4),
'efficientnet-b5': (1.6, 2.2, 456, 0.4),
'efficientnet-b6': (1.8, 2.6, 528, 0.5),
'efficientnet-b7': (2.0, 3.1, 600, 0.5),
'efficientnet-b8': (2.2, 3.6, 672, 0.5),
'efficientnet-l2': (4.3, 5.3, 800, 0.5),
- Efficientnet-B0的设置,这个设置和上面那张表是一样的
#r后面表示repeat,
#k表示kernel_size, s表示w和h的stride,
#e表示mobilenet里面的expansion ratio,
#i和o表示输入输出通道数,
#se表示se网络模块中的r参数。
'r1_k3_s11_e1_i32_o16_se0.25',
'r2_k3_s22_e6_i16_o24_se0.25',
'r2_k5_s22_e6_i24_o40_se0.25',
'r3_k3_s22_e6_i40_o80_se0.25',
'r3_k5_s11_e6_i80_o112_se0.25',
'r4_k5_s22_e6_i112_o192_se0.25',
'r1_k3_s11_e6_i192_o320_se0.25',
- 可以从代码看出有dropout rate,要注意的是不同的网络dropout_rate是不一样的,因为文章认为更大的网络,需要的正则力度更大。至于dropout放在哪呢,每个stride=1的MBConv后面都有。还有要特别注意的是这里的dropout不是往常常用的dropout,而是dropout connect,请参考文章[《Deep Networks with Stochastic Depth》]
- 网络中使用的激活函数是swish代替relu,但是se模块内的sigmoid函数不变。
- 网络中的se模块内的卷积是没有bn。
- efficientnet真的很efficient吗,博主自己用TensorFlow实现了一下,训练速度奇慢,Efficientnet-B0训练速度甚至比resnet50还慢。为什么呢?原因是TensorFlow对于depthwise卷积的并行实现的并不好。
https://github.com/tensorflow/tensorflow/issues/12132
https://github.com/tensorflow/tensorflow/issues/12940
欢迎加入Object Detection交流,群聊号码:910457072