简介
深度学习在图像分类,目标检测和图像分割等任务表现出了巨大的优越性。
但是伴随着模型精度的提升是计算量,存储空间以及能耗方面的巨大开销,对于移动或车载应用都是难以接受的。
之前的一些模型小型化工作是将焦点放在模型的尺寸上。
因此,在小型化方面常用的手段有:
(1)卷积核分解,使用1×N和N×1的卷积核代替N×N的卷积核
(2)使用bottleneck结构,以SqueezeNet为代表
(3)以低精度浮点数保存,例如Deep Compression
(4)冗余卷积核剪枝及哈弗曼编码
MobileNet进一步深入的研究了depthwise separable convolutions使用方法后设计出MobileNet,depthwiseseparable convolutions的本质是冗余信息更少的稀疏化表达。在此基础上给出了高效模型设计的两个选择:宽度因子(width multiplier)和分辨率因子(resolutionmultiplier);通过权衡大小、延迟时间以及精度,来构建规模更小、速度更快的MobileNet。Google团队也通过了多样性的实验证明了MobileNet作为高效基础网络的有效性。
一、深度可分离卷积
标准的卷积过程可以看上图,一个2×2的卷积核在卷积时,对应图像区域中的所有通道均被同时考虑,问题在于,为什么一定要同时考虑图像区域和通道?我们为什么不能把通道和空间区域分开考虑?
深度可分离卷积提出了一种新的思路:对于不同的输入channel采取不同的卷积核进行卷积,它将普通的卷积操作分解为两个过程。
卷积过程
假设有 N x H x W x C
的输入,同时有 k
个 3x3
的卷积。如果设置pad=1
且stride=1
,那么普通卷积输出为 N x H x W x k
。
Depthwise 过程
Depthwise是指将 N x H x W x C
的输入分为 group=C
组,然后每一组做3x3
卷积。这样相当于收集了每个Channel的空间特征,即Depthwise特征。
Pointwise 过程
Pointwise是指对 N x H x W x C
的输入做 k
个 1x1
卷积。这样相当于收集了每个点的特征,即Pointwise特征。Depthwise+Pointwise最终输出也是 N x H x W x k
。
深度可分离卷积结构
二、优势与创新
Depthwise+Pointwise可以近似看作一个卷积层:
- 普通卷积:3x3 Conv+BN+ReLU
- Mobilenet卷积:3x3 Depthwise Conv+BN+ReLU 和 1x1 Pointwise Conv+BN+ReLU
计算加速
参数量降低
假设输入通道数为3,要求输出通道数为256,两种做法:
1.直接接一个3×3×256的卷积核,参数量为:3×3×3×256 = 6,912
2.DW操作,分两步完成,参数量为:3×3×3 + 3×1×1×256 = 795(3个特征层(33的卷积核)),卷积深度参数通常取为1
乘法运算次数降低
对比一下不同卷积的乘法次数:
- 普通卷积计算量为:
HxWxCxkx3x3
- Depthwise计算量为:
HxWxCx3x3
- Pointwise计算量为:
HxWxCxk
通过Depthwise+Pointwise的拆分,相当于将普通卷积的计算量压缩为:
$$
\frac{\text {depthwise }+\text { pointwise }}{\operatorname{conv}}=\frac{H \times W \times C \times 3 \times 3+H \times W \times C \times k}{H \times W \times C \times k \times 3 \times 3}=\frac{1}{k}+\frac{1}{3 \times 3}
$$
通道区域分离
深度可分离卷积将以往普通卷积操作同时考虑通道和区域改变(卷积先只考虑区域,然后再考虑通道),实现了通道和区域的分离。
三、MobileNetV1 Gluon实现
可以自行输入查看打印的pdf的代码参数。
![](MobileNet architecture.png)
下面的Gluon的实现参考的Insightface_fmobilenet.py 。具体自行查看,注意num_filter
和num_group
之间的关系。例如,conv2_dw
的 num_group
等于 conv1
的num_filter
, conv2_dw
的 num_filter
是 conv2_dw
的num_group
的整数倍,依次类推。 注意分组卷积输出的是一个tuple类型,长度为1,所以可以看到下面Depthwise_Separable_conv
函数中第二个1x1的卷积的输入写的是conv_dw[0]
。
1 | # coding: gbk |
参考链接: