1、MobileNetV1
论文地址:https://arxiv.org/pdf/1704.04861.pdf
这篇论文是谷歌在2017年提出了,专注于移动端或者嵌入式设备中的轻量级CNN网络。该论文最大的创新点是,提出了深度可分离卷积(depthwise separable convolution)
设特征图尺寸为W*H,卷积核大小为k*k,输入通道数为c,有n个卷积核
传统的卷积计算量为W*H*k*k*c*(https://www.jianshu.com/p/2a0f3a4a9d1d)
深度可分离卷积(https://zhuanlan.zhihu.com/p/92134485)将传统卷积的两步进行分离开来,分别是depthwise和pointwise。从下面的图可以看出,首先按照通道进行计算按位相乘的计算,此时通道数不改变;然后依然得到将第一步的结果,使用1*1的卷积核进行传统的卷积运算,此时通道数可以进行改变。使用了深度可分离卷积,其计算量为k∗k∗c∗n∗H+1∗1∗c∗n∗W∗H。
使用传统卷积的准确率比深度可分离卷积的准确率高约1%,但计算量却增大了9倍。
网络结构
该网络有28层。可以看出,该网络基本去除了pool层,使用stride来进行降采样
2、MobileNetV2
论文地址:http://openaccess.thecvf.com/content_cvpr_2018/papers/Sandler_MobileNetV2_Inverted_Residuals_CVPR_2018_paper.pdf
发表于2018年,在V1的基础上引入了Inverted Residuals和Linear Bottlenecks。
倒残差模块
线性瓶颈
对低维度做ReLU运算,很容易造成信息的丢失。而在高维度进行ReLU运算的话,信息的丢失则会很少。另外一种解释是,高维信息变换回低维信息时,相当于做了一次特征压缩,会损失一部分信息,而再进过relu后,损失的部分就更加大了。作者为了这个问题,就将ReLU替换成线性激活函数。
把两个模块结合起来,stride=1时,输入首先经过1*1的卷积进行通道数的扩张,此时激活函数为ReLU6;然后经过3*3的depthwise卷积,激活函数是ReLU6;接着经过1*1的pointwise卷积,将通道数压缩回去,激活函数是linear;最后使用shortcut,将两者进行相加。而当stride=2时,由于input和output的特征图的尺寸不一致,所以就没有shortcut了。
3、MobileNetV3
论文地址:https://arxiv.org/pdf/1905.02244v5.pdf
代码实现:ensorflow:https://github.com/Bisonai/mobilenetv3-tensorflow
Pytorch:https://github.com/xiaolai-sqlai/mobilenetv3
改进
V3版本包含了深度可分离卷积、倒残差模块和线性瓶颈、SE模块,
1、利用NAS(神经结构搜索)来搜索网络的配置和参数
在网络结构搜索中,作者结合两种技术:资源受限的NAS(platform-aware NAS)与NetAdapt,前者用于在计算和参数量受限的前提下搜索网络的各个模块,所以称之为模块级的搜索(Block-wise Search) ,后者用于对各个模块确定之后网络层的微调,主要是确定每层的filter数量(Layer-wise Search)。
2、作者对耗费资源最多的输入输出层做了改进
3、由于嵌入式设备计算sigmoid是会耗费相当大的计算资源的,因此作者提出了h-switch作为激活函数。且随着网络的加深,非线性激活函数的成本也会随之减少。所以,只有在较深的层使用h-switch才能获得更大的优势。
4、引入SE模块
Squeeze-and-Excitation Networks,SE模块是一种轻量级的通道注意力模块,能够让网络模型对特征进行校准的机制,使得有效的权重大,无效或效果小的权重小的效果。
MobileNetV3的SE模块被运用在线性瓶颈结构最后一层上,代替V2中最后的逐点卷积,改为先进行SE操作再逐点卷积。这样保持了网络结构每层的输入和输出,仅在中间做处理。
网络结构
MobileNetV3分为Large和Small两个版本,Large版本适用于计算和存储性能较高的平台,Small版本适用于硬件性能较低的平台。