V1
MobileNet是基于深度可分离卷积的。通俗的来说,深度可分离卷积干的活是:把标准卷积分解成深度卷积(depthwise convolution)和逐点卷积(pointwise convolution)。这么做的好处是可以大幅度降低参数量和计算量。分解过程示意图如下
标准卷积
采用的标准卷积K为 ( D K , D K , M , N ) (D_K,D_K,M,N) (DK,DK,M,N),输出的特征映射为G尺寸为 ( D F , D F , N ) (D_F,D_F,N) (DF,DF,N),
所以标准卷积计算量为 D F ∗ D F ∗ N ∗ D K ∗ D K ∗ M D_F*D_F*N*D_K*D_K*M DF∗DF∗N∗DK∗DK∗M
深度可分离卷积
本文做法是用(b)+(c)代替(a)
(1)深度卷积
即图中(b)所示,用M个维度为
D
K
∗
D
K
∗
1
D_K*D_K*1
DK∗DK∗1的卷积核去卷积对应输入特征图的M个通道,得到特征图
D
F
∗
D
F
∗
M
D_F*D_F*M
DF∗DF∗M,这一步计算量为
D
F
∗
D
F
∗
M
∗
D
K
∗
D
K
D_F*D_F*M*D_K*D_K
DF∗DF∗M∗DK∗DK
(2)逐点卷积
上一步得到特征图
D
F
∗
D
F
∗
M
D_F*D_F*M
DF∗DF∗M,用N个维度为1* 1* M的卷积进行卷积,得到输出
(
D
F
,
D
F
,
N
)
(D_F,D_F,N)
(DF,DF,N),这一步计算量为
D
F
∗
D
F
∗
N
∗
M
D_F*D_F*N*M
DF∗DF∗N∗M
所以最后计算量比值为
如果使用3*3卷积,那么卷积操作计算量可以降到原来1/9左右!
网络结构
![](https://i-blog.csdnimg.cn/blog_migrate/4c249442f55156b61f53de8f796fc338.png)
代码参考
https://github.com/Zehaos/MobileNet/blob/master/nets/mobilenet.py
核心就是下面几段代码
# skip pointwise by setting num_outputs=None
depthwise_conv = slim.separable_convolution2d(inputs,
num_outputs=None,
stride=_stride,
depth_multiplier=1,
kernel_size=[3, 3],
scope=sc+'/depthwise_conv')
bn = slim.batch_norm(depthwise_conv, scope=sc+'/dw_batch_norm')
pointwise_conv = slim.convolution2d(bn,
num_pwc_filters,
kernel_size=[1, 1],
scope=sc+'/pointwise_conv')
bn = slim.batch_norm(pointwise_conv, scope=sc+'/pw_batch_norm')
v2
- Inverted residuals,通常的residuals block是先经过一个11的Conv layer,把feature map的通道数“压”下来,再经过33 Conv layer,最后经过一个1*1 的Conv layer,将feature map 通道数再“扩张”回去。即先“压缩”,最后“扩张”回去。
而 inverted residuals就是 先“扩张”,最后“压缩”。
2.Linear bottlenecks,为了避免Relu对特征的破坏,在residual block的Eltwise sum之前的那个 1*1 Conv 不再采用Relu。