当前很多轻量级网络会经常使用到MobileNetv3
,本文将讲解google继MobileNetv2
之后提出的v3版本。MobileNetv3论文
:Searching for MobileNetV3
根据MobileNetV3论文总结,网络存在以下3点需要大家注意的:
更新了Block(bneck)
,在v3版本中原论文称之为bneck
,在v2版倒残差结构
上进行了简单的改动。Neural Architecture Search
)搜索参数重新设计了耗时结构
:作者使用NAS
搜索之后得到的网络,接下来对网络每一层的推理时间进行分析,针对某些耗时的层结构做了进一步的优化MobileNetV3性能提升
MobileNetV3-Large
is3.2%
moreaccurate
on ImageNet classification while reducinglatency by 20%
compared toMobileNetV2
.MobileNetV3-Small
is6.6%
more accuratecompared to a MobileNetV2
model with comparable latency. MobileNetV3-Large detection is over 25% faster at roughly the same accuracy as MobileNetV2 on COCO detection. MobileNetV3-Large LRASPP is 34% faster than MobileNetV2 R-ASPP at similar accuracy for Cityscapes segmentation
(V3-Large 1.0)
的Top-1
是75.2
,对于V2 1.0
它的Top-1
是72
,相当于提升了3.2%
(V3-Large 1.0)
在P-1
手机上推理时间为51ms
,而V2
是64ms
,很明显V3
比V2
,不仅准确率更高了,而且速度更快了V3-Small
版本的Top-1
是 67.4
,而V2 0.35
(0.35表示卷积核的倍率因子)的Top-1
只有60.8
,准确率提升了6.6%
很明显V3版本比V2版本要更优秀
1x1
卷积层来进行升维处理,在卷积后会跟有BN
和ReLU6
激活函数3x3
大小DW
卷积,卷积后面依旧会跟有BN
和ReLU6
激活函数1x1
卷积,起到降维作用,注意卷积后只跟了BN
结构,并没有使用ReLU6
激活函数。另外网络还存在一个捷径分支shotcut
,将我们输入特征矩阵与输出特征矩阵在相同维度的数值上进行相加操作。并且只有DW
卷积的步距为1,且input_channel==output_channel
,才有shotcut
连接
咋一看,与MobieNetV2 Block
也没什么区别,最显眼的区别就是在MobieNetV3 Block
中存在SE
模块(注意力机制)
SE模块
对得到的特征矩阵,对每个channel
进行池化处理,接下来通过两个全连接层
得到输出的向量,其中第一个全连接层,它的全连接层节点数
是等于输入特征矩阵channel
的1/4,第二个全连接层的channel
是与我们特征矩阵的channel
保持一致的。经过平均池化+两个全连接层,输出的特征向量可以理解为是对SE之前的特征矩阵的每一个channel分析出了一个权重关系,它认为比较重要的channel
会赋予一个更大的权重,对于不是那么重要的channel
维度上对应一个比较小的权重
如上图所示:假设我们特征矩阵的channel
为2,使用Avg pooling
针对每一个channel
去求一个均值,因为有两个channel,所以得到2个元素的向量
,然后依次在经过两个全连接层,第一个channel为原来channel的1/4,并且对应relu
激活函数。对于第二个全连接层它的channel和我们特征矩阵channel
维度是一致的,注意这里使用的激活函数使h-sigmod
,然后得到和特征矩阵channel大小一样的向量,每个元素就对应于每个channel的权重
.比如第一个元素是0.5,将0.5与特征矩阵第一个channel的元素相乘,得到一个新的channel数据。
另外网络更新了激活函数
对应图中的NL
表示的就是非线性激活函数,在不同层中使用的激活函数不一样,这里没有给出一个明确的激活函数,而是标注了一个NL
,注意最后一层1x1
的卷积是没有使用非线性激活函数的,用的是线性激活函数。
MobieNetV3 Block和MobieNetV2 Block结构基本是一样的,主要是增加了
SE结构,并对激活函数进行了更新
在原论文中主要讲了两个部分:
减少第一个卷积层的卷积个数(32 -> 16)
2ms
的运算时间精简 Last Stage
NAS
搜索出来的网络结构的最后一部分,叫做Original last Stage
,它的网络结构如下:Original Last Stage
是一个比较耗时的部分,作者就针对该结构进行了精简,提出了一个Efficient Last Stage
Efficient Last Stage
相比之前的Original Last Stage
,少了很多卷积层,作者发现更新网络后准确率是几乎没有变化的,但是节省了7ms
的执行时间。这7ms
占据了推理11%
的时间,因此使用Efficient Last Stage
之后,对我们速度提升还是比较明显的。
之前在v2版本我们基本都是使用ReLU6
激活函数,现在比较常用的激活函数叫swish
激活函数。
s
w
i
t
h
x
=
x
.
σ
(
x
)
swith x=x.\sigma(x)
swithx=x.σ(x)
其中
σ
\sigma
σ的计算公式如下:
σ
(
x
)
=
1
1
+
e
−
x
\sigma(x)=\frac{1}{1+e^{-x}}
σ(x)=1+e−x1
使用switch
激活函数之后,确实能够提高网络的准确率,但是也存在2个问题:
由于存在这个问题,作者就提出了h-switch
激活函数,在讲h-switch
激活函数之前我们来讲一下h-sigmoid
激活函数
h-sigmoid
激活函数是在relu6
激活函数上进行修改的:
R
E
L
U
6
(
x
)
=
m
i
n
(
m
a
x
(
x
,
0
)
,
6
)
RELU6(x)=min(max(x,0),6)
RELU6(x)=min(max(x,0),6)
h
−
s
i
g
m
o
i
d
=
R
e
L
U
6
(
x
+
3
)
6
h-sigmoid=\frac{ReLU6(x+3)}{6}
h−sigmoid=6ReLU6(x+3)
从图中可以看出h-sigmoid
与sigmoid
激活函数比较接近,所以在很多场景中会使用h-sigmoid
激活函数去替代我们的sigmoid
激活函数。因此h-switch
中
σ
\sigma
σ替换为h-sigmoid
之后,函数的形式如下:
h
−
s
w
i
t
c
h
[
x
]
=
x
R
e
L
U
6
(
x
+
3
)
6
h-switch[x]=x\frac{ReLU6(x+3)}{6}
h−switch[x]=x6ReLU6(x+3)
如上图右侧部分,是switch
和h-switch
激活函数的比较,很明显这两个曲线是非常相似的,所以说使用h-switch
来替代switch
激活函数还是挺棒的。
在原论文中,作者说将h-switch
替换switch
,将h-sigmoid
替换sigmoid
,对于网络的推理过程而言,在推理速度上是有一定帮助的,并且对量化过程也是非常友好的。
简单看下表中各参数的含义:
input
输入层特征矩阵的shapeoperator
表示的是操作,对于第一个卷积层conv2d;这里的#out
代表的输出特征矩阵的channel,我们说过在v3版本中第一个卷积核使用的是16
个卷积核NL
代表的是激活函数,其中HS
代表的是hard switch
激活函数,RE
代表的是ReLU激活函数;s
代表的DW
卷积的步距;exp size
代表的是第一个升维的卷积,我们要将维度升到多少,exp size
多少,我们就用第一层1x1
卷积升到多少维。SE
:表示是否使用注意力机制,只要表格中标√
所对应的bneck
结构才会使用我们的注意力机制,对没有打√
就不会使用注意力机制NBN
最后两个卷积的operator提示NBN
,表示这两个卷积不使用BN
结构,最后两个卷积相当于全连接的作用注意
:第一个bneck
结构,这里有一点比较特殊,它的exp size
和输入的特征矩阵channel是一样的,本来bneck
中第一个卷积起到升维
的作用,但这里并没有升维。所以在实现过程中,第一个bneck
结构是没有1x1
卷积层的,它是直接对我们特征矩阵进行DW
卷积处理1x1
卷积进行升维到exp size
,通过DW
卷积它的维度是不会发生变化的,同样通过SE之后channel也会不会发生变化的。最后通过1x1
卷积进行降维处理。降维后的channel
对应于#out
所给的数值。shortcut
捷径分支,必须是DW
卷积的步距为1,且bneck
的input_channel=output_channel
才有shortcut
连接通过这个表我们就可以搭建MobilenetV3
网络结构了
对于MobileNetV3-Small
网络结构,如下,这里就不讲了,跟我所讲的基本上都一致的。