论文地址: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(指的是网络的输入图片大小),放大上述三方面的比例因子分别用表示。三个维度如下图所示:
上图如果不仔细看容易误解,仔细看上图最左边的图,才能很好的理解所代表的维度。
结论1
对于width、depth、resolution三个方向,文章都分别的举了一些例子来说明观察到的一个结论,这个结论就是,从上述三个方面来放大网络都能是的网络的精度得到题设,但是对于大的网络来说提升的效果是有限的。
结论2
文章提到上述的三个维度不是相互独立的,从直觉上来讲,对于输入的图片分辨率更高的情况,需要有更深的网络来获得更大的感受野。同样的,对于更高分辨率的图片,需要有更多的通道来获取更精确的特征。这也说明这三个维度的的放大系数是不独立的。
这就得到了有一个结论,为了得到更高的精度,网络三个维度的放大不是独立的,有一个平衡的条件。
为了将网络的放大更为的方便,文章提出compound scaling method的概念,就是希望通过一个参数来控制网络的放大程度,这个参数用表示。文章规定放大网络有下列的原则:
为什么depth没有平方,其余的有平方项。因为对于flops来说,depth增加一倍,计算量增加一倍,但是其余两项都是对应维度增加一倍,计算量增加4倍。至于为什么,嗯,这是文章规定的。当时,网络计算量增加。
二、网络结构
网络结构没啥可说的,文章类似MnasNet,采用nas方式搜索得到一个基本网络结构Efficientnet-B0,网络结构如下表所示:
2.png
表中Conv表示的是标注卷积,MBConv表示的是类似于mobilenet中的inverted bottleneck,不同的是mobilenet全是的卷积,这里还有大小的卷积,而且在bottleneck中还加入了se模块(详情查看SENet(Squeeze-and-Excitation Networks)论文详解
)。
文章通过Efficientnet-B0的网络结构和上面讲的网络放大因子的网格搜索方式得到了Efficientnet家族,称为Efficientnet-B0~Efficientnet-B7。文章做法是:
- 先固定,调节,得到B0的一组好的参数,
- 固定上述得到的值,然后调节,得到Efficientnet-B1~Efficientnet-B7。
关于网络的效果,可以查看文章,下面关于实现还要多说两句。
- 对于值,代码设置如下,如下:
# (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
网友评论