7.1 MobileNet网络详解_哔哩哔哩_bilibili
在移动端部署深度卷积网络,无论什么视觉任务,选择高精度的计算量少和参数少的骨干网是必经之路。轻量化网络是移动端的研究重点。
传统卷积神经网络,内存需求大、运算量大 导致无法在移动设备以及嵌入式设备上运行
MobileNet网络是由google团队在2017年提出的,专注于移动端或者嵌入 式设备中的轻量级CNN网络。相比传统卷积神经网络,在准确率小幅降 低的前提下大大减少模型参数与运算量。(相比VGG16准确率减少了0.9%, 但模型参数只有VGG的1/32)
论文:
Pointwise Conv:
理解:常规的卷积(标准卷积)是把每一个卷积核作用在输入图像的所有通道,并将他们整合在一起,形成一个通道输出。
如下图所示,普通卷积和深度可分卷积最后同样得到深度为4的特征矩阵
:输入特征矩阵的高和宽
: 卷积核的大小
M : 输入特征矩阵的深度
N : 输出特征矩阵的深度,对应卷积核的个数
普通卷积: · · M · N · ·
这个公式的理解是: 前面四个是计算出参数的个数,后面两个DF是每个参数要参与计算的次数,得出来计算量
DW+PW: · · M · · + M · N · ·
理论上普通卷积计算量是 DW + PW 的8到9倍
和vgg网络比较相似,是大量卷积核的堆叠组成
Multiply-Add 计算量
超参数 Width Multiplie Resolution Multiplier
正确率小幅度的下降换来计算量的大幅度减少
缺点:depthwise部分的卷积核容易费掉,即卷积核参数大部分为零。
MobileNet v2网络是由google团队在2018年提出的,相比MobileNet V1网 络,准确率更高,模型更小
论文:
网络中的亮点:
1. 左侧为ResNet网络提供的残差结构:对于输入特征矩阵,采用1 * 1 的卷积核对输入特征矩阵进行压缩,也就是减少输入特征矩阵的channel,再通过3 * 3 的卷积核进行卷积处理,最后采用 1 * 1的卷积核对channel进行扩充,就形成了两头大,中间小的一个瓶颈结构。
使用的激活函数为Relu
2. 右侧为MobileNet_v2 结构的倒残差结构,首先采用1 * 1 的卷积核进行升维操作,将channel便的更深,在通过卷积核大小为3 * 3 的 DW 操作进行卷积,最后通过1 * 1的卷积进行降维处理。
使用的激活函数是Relu6
下图为Relu函数,小于0时置零,大于0不做处理
下图为 Relu6 激活函数,小于0时置零,在0-6这个区间同样不做处理,当输入值大于6时就将输入值全部置为6
在原文中,针对倒残差结构的最后一个1 * 1 的卷积层,使用了线性的激活函数,而不是之前所说的 Relu 激活函数,为什么这样做,原文做了一个实验:
首先输入是一个二维矩阵,它的channel等于1;
采用不同维度的矩阵matrix T 将它进行变换,把它变到更高的维度;
在使用一个Relu激活函数得到一个输出值;
在使用 T 矩阵的逆矩阵 ,将输出矩阵还原回二维的特征矩阵;
当matrix T =2,3 的时候,如上图2,3,可以发现,此时丢失了很多信息;
当matrix T 不断变大时,丢失的信息越来越少了。
结论:ReLU激活函数对低维特征信息照 成大量损失,对高维特征信息造成的损失很少。因为倒残差结构是两边细,中间粗的结构,所以输出时是低维的特征向量,所以要使用一个线性的激活函数替代relu函数来避免信息损失。
对应下图中的结构信息
第一层:h,w,k分别为高宽和深度,1 * 1的卷积核进行升维处理,t 为扩展因子,1 * 1的卷积个数等于tk,所以输出特征矩阵的深度为tk;
第二层:输入为上一层的输出,3 * 3大小的DW卷积核,步距为s,输出特征矩阵的深度和输入特征矩阵的深度是一样的,由于步距为s,所以高和宽变为原来的s分之一倍;
第三层:1 *1 的卷积层进行降维,卷积核个数为k’,将特征矩阵的深度由tk变为k‘
当stride=1且输入特征矩阵与输出特征矩阵shape相同时才有shortcut连接,不满足这个条件时都是没有shortcut连接的。
网络结构的参数:
t 为扩展因子
c为输出特征矩阵的channel,为前文中的k’
n代表bottleneck重复的次数,bottleneck其实就是论文中的倒残差结构
s是步距(针对第一层,其他层为1)
性能对比:
Classification
Object Detection
论文:
改进:
由下图可以看出,v3 更准确,更高效
1.加入SE模块(注意力机制)
2.更新了激活函数
当stride == 1且 input_c == output_c 才有shortcut连接
Mobilenet V3 的注意力机制如图黄色部分所示
对得到的特征矩阵的每个channel进行池化处理, 特征矩阵的channel有多少,得到的一维向量就有多少个元素,再通过两个全连接层得到输出的向量;
第一个全连接层的节点个数就等于特征矩阵channel的1/4,第二个全连接层的节点个数和特征矩阵的channel个数保持一致;
输出的向量就是对每一个channel分析出一个权重关系,它认为比较重要的channel就赋予更大的权重,它认为不是很重要的channel就赋予小的权重。
用下面的图加深理解
假设特征矩阵的channel等于2;
首先采用平均池化操作求每个channel的平均值,得到元素个数为2的一个向量;
再依次经过两个全连接层:
FC1的节点个数是特征矩阵channel的1/4,使用的是Relu激活函数
FC2的节点个数和特征矩阵的channel保持一致,使用的是H-sig激活函数
得到有两个元素的向量,对应每个channel的权重,用第一个权重0.5和第一个channel中的所有元素相乘,得到一个新的channel数据
注意:最后1*1的降维卷积层没有使用激活函数
1.减少第一个卷积层的卷积核个数(32->16)
2.精简Last Stage
原文中说用更少的卷积核个数可以达到一样的准确率
Efficient Last Stage 和上面比起来明显少了很多结构,调整之后再准确率上是没有变化的,但节省了7ms的时间
使用swish确实可以提高网络的准确率,但是计算、求导复杂, 对量化过程不友好,特别是对移动端设备非常不友好,所以作者提出了h-swish激活函数,但需要先看h-sigmoid激活函数;
如图 h-sigmoid 和 sigmoid 函数比较接近,所以再很多场合就用 h-sigmoid 替代了sigmoid
所以就从h-sigmoid替代 函数,得到 h-swish 激活函数;
如图swish和h-swish曲线非常相似,替换后再速度上是有一定帮助的,对于量化过程也非常友好。
out:输出特征矩阵的channel,降维后对应的channel;
NL :激活函数,分为两种;
s : 步距;
exp size:升维的卷积,给的值是多少,就利用1 * 1的卷积升维;
SE:代表是否使用注意力机制;
NBN:表示不适用BN结构
注意:第一个bneck和输入特征矩阵的channel是一样的,并没有升维,所以在第一个bneck中是没有第一个1 * 1的卷积层的,直接对特征矩阵进行DW操作的