v1: (1)单片卷积 + 1x1 通道改维度;
(2)宽度因子a + 分辨率因子 b ; (以最低的精度损失换取大量的参数减少)
v2: (1)加入残差结构(先升维:增加信息量,再降维度:较少参数,与Resnet相反),增加梯度传播
(2)较少block最后的Relu,为lineat,减少信息破坏;
(3)全卷积(减少参数)+relu6(采用float16,防止数值爆炸)
文章目录
一、参数数量和理论计算量
1、定义
- 参数数量(params):关系到模型大小,单位通常为M,通常参数用 float32 表示,所以
模型大小是参数数量的 4 倍
- 理论计算量(FLOPs):
- 是 floating point operations 的缩写(注意 s 小写),可以用来
衡量算法/模型的复杂度
,这关系到算法速度,大模型的单位通常为 G,小模型单位通常为 M- 通常只考虑乘加操作
(Multi-Adds)
的数量,而且只考虑CONV 和 FC
等参数层的计算量,忽略 BN 和PReLU 等等。一般情况,CONV 和 FC 层也会忽略仅纯加操作
的计算量,如 bias 偏置加和 shotcut 残差加等,目前技术有 BN 的 CNN 可以不加 bias
2、计算公式
假设卷积核大小为 Kh×KwK_h \times K_wKh×Kw,输入通道数为 CinC_{in}Cin,输出通道数为 CoutC_{out}Cout,输出特征图的宽和高分别为 WWW 和 HHH,这里忽略偏置项
CONV 标准卷积层:
- params: Kh×Kw×Cin×CoutK_h \times K_w \times C_{in} \times C_{out}Kh×Kw×Cin×Cout
- FLOPs:Kh×Kw×Cin×Cout×H×W=params×H×WK_h \times K_w \times C_{in} \times C_{out} \times H \times W = params \times H \times WKh×Kw×Cin×Cout×H×W=params×H×W
FC 全连接层(相当于 k=1):
- params: Cin×CoutC_{in} \times C_{out}Cin×Cout
- FLOPs:Cin×CoutC_{in} \times C_{out}Cin×Cout
二、MobileNetV1: Efficient Convolutional Neural Networks for Mobile Vision Application
1、能够减少参数数量和计算量的原理
- 深度可分离卷积的使用
- 在进行 depthwise 卷积时只使用了
一种
维度为in_channels
的卷积核进行特征提取(没有进行特征组合) - 在进行 pointwise 卷积时只使用了
output_channels 种
维度为in_channels
1*1 的卷积核进行特征组合,普通卷积不同 depth 层的权重是按照 1:1:1…:1的比例进行相加的,而在这里不同 depth 层的权重是按照 不同比例(可学习的参数) 进行相加的 - 参数数量由原来的
p1 = F*F*in_channels*output_channels
变为了p2 = F*F*in_channels*1 + 1*1*in_channels*output_channels
,减小为原来的p2/p1 = 1/output_channels + 1/F*F
,其中 F 为卷积核的尺寸,若 F=3F = 3F=3,参数量大约会减少到原来的 1/8→1/91/8 \to 1/91/8→1/9 - Note: 原论文中对第一层没有用此卷积,深度可分离卷积中的每一个后面都跟 BN 和 RELU
- 在进行 depthwise 卷积时只使用了
- Global Average Pooling 的使用:这一层没有参数,计算量可以忽略不计
- 用
CONV/s2
(步进2的卷积)代替MaxPool+CONV
:使得参数数量不变,计算量变为原来的 1/4 左右,且省去了MaxPool 的计算量 - Note:采用 depth-wise convolution 会有一个问题,就是导致
信息流通不畅
,即输出的 feature map 仅包含输入的 feature map 的一部分
,在这里,MobileNet 采用了 point-wise(1*1) convolution 帮助信息在通道之间流通
2、MobileNetV1 中引入的两个超参数
- Width Multiplier(α\alphaα): Thinner Models
- 所有层的 通道数(channel) 乘以 α\alphaα 参数(四舍五入),模型大小近似下降到原来的 α2\alpha^{2}α2 倍,计算量下降到原来的 α2\alpha^{2}α2 倍
- α∈(0,1]\alpha \in (0, 1]α∈(0,1] with typical settings of 1, 0.75, 0.5 and 0.25,降低模型的宽度
- Resolution Multiplier(ρ\rhoρ): Reduced Representation
- 输入层的 分辨率(resolution) 乘以 ρ\rhoρ 参数 (四舍五入),等价于所有层的分辨率乘 ρ\rhoρ,模型大小不变,计算量下降到原来的 ρ2\rho^{2}ρ2 倍
- ρ∈(0,1]\rho \in (0, 1]ρ∈(0,1],降低输入图像的分辨率
3、标准卷积和深度可分离卷积的区别
4、TensorFlow 中的代码实现
- 可使用 tensorflow 中的
tf.nn.separable_conv2d()
来实现, 参数depthwise_filter
中的channel_multiplier 设为 1
即可
# 使用 slim 来实现
def _depthwise_separable_conv(inputs,
num_pwc_filters,
kernel_width,
phase,
sc,
padding='SAME',
width_multiplier=1,
downsample=False):
""" Helper function to build the depth-wise separable convolution layer.
"""
num_pwc_filters = round(num_pwc_filters * width_multiplier)
_stride = 2 if downsample else 1
# skip pointwise by setting num_outputs=None
depthwise_conv = slim.separable_convolution2d(inputs,
num_outputs=None,
stride=_stride,
depth_multiplier=1,
kernel_size=[kernel_width, kernel_width],
padding=padding,
activation_fn=None,
scope=sc + '/depthwise_conv')
bn = slim.batch_norm(depthwise_conv, activation_fn=tf.nn.relu, is_training=phase, scope=sc + '/dw_batch_norm')
pointwise_conv = slim.convolution2d(bn,
num_pwc_filters,
kernel_size=[1, 1],
activation_fn=None,
scope=sc + '/pointwise_conv')
bn = slim.batch_norm(pointwise_conv, activation_fn=tf.nn.relu, is_training=phase, scope=sc + '/pw_batch_norm')
return bn
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
5、Caffe 中的代码实现
三、MobileNetV2:Inverted Residuals and Linear Bottlenecks
1、主要改进点
- 引入残差结构,先升维再降维,增强梯度的传播,显著减少推理期间所需的内存占用(
Inverted Residuals
) - 去掉 Narrow layer(low dimension or depth) 后的 ReLU,保留特征多样性,增强网络的表达能力(
Linear Bottlenecks
) - 网络为
全卷积
的,使得模型可以适应不同尺寸的图像;使用RELU6(最高输出为 6)
激活函数,使得模型在低精度计算下具有更强的鲁棒性 - MobileNetV2 building block 如下所示,若需要下采样,可在 DWise 时采用
步长为 2
的卷积;小网络使用小的扩张系数(expansion factor
),大网络使用大一点的扩张系数(expansion factor),推荐是5~10,论文中 t=6t = 6t=6