参考:
- MobileNet V2 论文初读: https://zhuanlan.zhihu.com/p/33075914
- CNN模型之MobileNet(知乎:我是小将): https://zhuanlan.zhihu.com/p/31551004
- (nice):https://www.cnblogs.com/ansang/p/9076253.html
- https://yinguobing.com/bottlenecks-block-in-mobilenetv2/#fn2
- MobileNetV2的翻译:https://blog.csdn.net/u011974639/article/details/79199588
- https://zhuanlan.zhihu.com/p/33052910
目前的研究总结来看分为两个方向:
- 一是对训练好的复杂模型进行压缩得到小模型;
- 二是直接设计小模型并进行训练。
代码实现
MobileNet(非官方):https://github.com/xiaohu2015/DeepLearning_tutorials/blob/master/CNNs/MobileNet.py
可分离卷积Separable Convolution
包含两个步骤:
- depth-wise convolution
- Pointwise convolution
之前在 Xception 中被广泛使用。这么做的好处是理论上可以成倍的减少卷积层的时间复杂度和空间复杂度。
详细的介绍见:
https://yinguobing.com/separable-convolution/
MobileNet
Depth-wise convolution 可以看成是特殊的 group convolution,即每一个通道是一组。
block:
网络结构:
如果单独计算depthwise
convolution和pointwise convolution,整个网络有28层(这里Avg Pool和Softmax不计算在内)。
MobileNetv2
改进1:Linear Bottleneck:
==1x1卷积降维后,应该用线性激活代替ReLU==。
设计原因:在MobileNet V1中做了一个实验是用width multiplier参数来做模型通道的缩减,相当于给模型“瘦身”,这样特征信息就能更集中在缩减后的通道中,但是如果此时加上一个非线性激活层,比如ReLU,就会有较大的信息丢失,因此为了减少信息丢失,就用linear激活函数,即不用激活函数。
改进2:Inverted residuals
经典的残差块是先降维再升维(像沙漏一样,中间窄,两边宽):input -> 1x1(压缩) -> 3x3(卷积) -> 1x1(升维)
==而inverted residual则是先升维后降维(梭子形):input -> 1x1(升维) -> 3x3(dw conv+relu) -> 1x1(降维+线性激活),skip-connection是在低维的瓶颈层间发生的==(如下图):
设计原因:目的是为了提升通道数,获得更多特征信息。
block结构对比
注:模型中使用 ReLU6 作为非线性层,在低精度计算时能压缩动态范围,算法更稳健。
ReLU6 定义为:f(x) = min(max(x, 0), 6),详见 tf.nn.relu6 API 手册[1]。