1.MobileNetv1网络详解
传统卷积神经网络专注于移动端或者嵌入式设备中的轻量级CNN网络,相比于传统卷积神经网络,在准确率小幅降低的前提下大大减少模型参数与运算量。(相比VGG16准确率减少了0.9%,但模型参数只有VGG的1/32)
网络的创新点:
(1)Depthwise Coinvolution(大大减少运算量和参数数量)
(2)增加超参数α、β
(1)Depthwise Coinvolution
传统卷积:卷积核channel = 输入特征矩阵channel
输出特征矩阵channel = 卷积核个数

DW卷积(Depthwise Conv): 卷积核channel = 1
输入特征矩阵channel = 卷积核个数 = 输出特征矩阵channel

PW卷积(Pointwise Conv):与普通卷积类似,但是卷积核大小为1

深度可分卷积(Depthwise Separable Conv):将DW卷积和PW卷积一起使用,理论上普通卷积核计算量是DW+PW的8~9倍。
(关于计算量的细节可以看MobileNetv1原论文的3.1和3.2章节)
MobileNetv1网络参数
Conv表示普通卷积,3x3x3x32表示卷积核的高x宽x输入特征矩阵深度x卷积核个数;
Conv dw表示dw卷积,3x3x32表示卷积核的高x宽x输入特征矩阵深度(dw中为1)x卷积核个数。

(2)超参数α、β
α(Width Multiplier):卷积核个数倍率,控制卷积过程中采用卷积核个数

β(Resolution Multiplier):输入图像分辨率参数

在MobileNetv1网络的实际使用中会发现dw卷积的部分卷积核容易废掉(即卷积核参数为0),针对这个问题在MobileNetv2网络有所改善
2.MobileNetv2网络详解
网络的创新点:
(1)Inverted Residuals(倒残差结构)
(2)Linear Bottlenecks
(1)Inverted Residuals(倒残差结构)
ResNet的残差结构:对于输入特征矩阵采用1x1卷积进行压缩,再通过3x3卷积核进行卷积处理,最后再采用1x1卷积核扩充channel
倒残差结构:对于输入特征矩阵采用1x1卷积核将channel变得更深,再通过3x3的卷积核进行dw卷积,最后再采用1x1卷积核进行降维处理

在普通残差结构中采用的是ReLU激活函数,在倒残差结构中采用的是ReLU6激活函数:

倒残差结构图:
当stride=1且输入特征矩阵与输出特征矩阵shape相同时才有shortcut连接。

(2)Linear Bottlenecks
针对倒残差结构的最后一个1x1卷积层,使用了线性激活函数,而不是ReLU激活函数
在原论文中作者通过实验得出:ReLU激活函数会对低维特征信息造成大量损失,对高维造成损失比较小,而在倒残差结构中的输出是一个低维特征向量,因此使用线性激活函数避免特征信息损失。
MobileNetv2模型参数
t是扩展因子,即倒残差结构第一层1x1卷积核个数的扩展倍率;
c是输出特征矩阵的深度channel;
n是bottleneck的重复次数,对应论文中的到残差结构;
s是步长,代表每一个block所对应的第一层bottleneck的步长,其他的为1。如n=2时,bottleneck的重复2遍,第一层bottleneck的步长为s,第二层bottleneck的步长为1。(一个block由一系列bottleneck组成)

在第一个bottleneck中t=1,即第一层卷积层没有对输入特征矩阵的深度进行调整。在pytorch和tensorflow中没有使用1x1卷积层,因为没有起到作用。
3.使用Pytorch搭建MobileNetv2网络
文件结构:
MobileNetv2
├── model_v2.py: MobileNetv2模型搭建
├── model_v3.py: MobileNetv3模型搭建
├── train.py: 训练脚本
└── predict.py: 图像预测脚本
1.model_v2.py
定义Conv+BN+ReLU6的组合层
class ConvBNReLU(nn.Sequential): #定义Conv+BN+ReLU6的组合层,继承nn.Sequential副类(根据Pytorch官方样例,要使用官方预训练权重)
def __init__(self, in_channel, out_channel, kernel_size=3, stride=1, groups=1): #初始化函数,在pytorch中dw卷积也是调用的nn.Conv2d类,如果传入groups=1则为普通卷积;如果groups=in_channel则为dw卷积
padding = (kernel_size - 1) // 2 #卷积过程中需要设置的填充参数
super(ConvBNReLU, self).__init__(
nn.Conv2d(in_channel, out_channel, kernel_size, stride, padding, groups=groups, bias=False), #卷积,groups默认为1
nn.BatchNorm2d(out_channel),

最低0.47元/天 解锁文章
5818

被折叠的 条评论
为什么被折叠?



