本文为MobileNet系列论文阅读笔记。MobileNet是一个轻量级模型,参数少、推理快,在学术界和工业界都很受欢迎。
目录
一、MobileNetV1
1、 Depthwise Separable Convolution
2、网络结构
3、实验结果
二、MobileNetV2
1、Linear Bottlenecks
2、 Inverted residuals
3、网络结构
三、MobileNetV3
1、SE(Sequeeze and Excite)
2、Nonlinearities
3、网络结构
4、实验结果
论文:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
MobileNetV1中提出使用深度可分离卷积替代普通卷积来减少模型参数。
假设卷积层的输入维度为[N, Ci, H, W],输出的维度为[N, Co, H, W],那么普通卷积的卷积核为[Co, Ci, K1, K2],参数数量为Co*Ci*K1*K2。
但是将其转换为深度可分离卷积后,参数数量为Ci*K1*K2+Ci*Co。
具体过程如下,首先使用[Ci, K1, K2]的卷积核与特征图做depth-wise conv(每个滤波器和特征图逐层卷积运算),得到[N, Ci, H, W]的特征图,然后使用[Co, Ci, 1, 1]的特征图做point-wise conv,得到[N, Co, H, W]的特征图。普通卷积和深度可分离卷积的参数数量比例如下,当K1=K2=3时,普通卷积的参数数量约为深度可分离卷积参数数量的9倍。
深度可分离卷积的depth-wise和point-wise卷积后都接BN和ReLU。
具体网络结构如下,dw代表深度可分离卷积,S2代表步长为2。为了动态调整模型的大小,引入通道缩放因子α,可根据需要自适应调整模型大小。
不同缩放程度的MobileNet在ImageNet上的效果如下表。
论文:MobileNetV2: Inverted Residuals and Linear Bottlenecks
MobileNetV2在MobileNetV1的基础上,提出了2点创新:
(1)使用linear bottleneck捕获“manifold of interest”;
(2)逆残差模块;
经过ReLU激活函数的特征图,有部分输入值变为0,有的保留不变。从而使得输出特征图中只包含部分有用特征(文中叫manifold of interest),那么可以设计一种结构仅提取出这些有用特征。作者用point-wise的conv+bn来提取有用特征(压缩了通道数,没有relu)。
下图为几种结构:
(a)普通卷积
(b)MobileNetV1中的深度可分离卷积
(c)可分离卷积带linear bottlenecks
(d)MobileNetV2使用的膨胀卷积块,expansion系数一般取5-10
当多个模块堆叠的时候,(c)和(d)是一样的。
正常的残差结构是类似于瓶颈的结构(2边通道多,中间通道少,和瓶颈形状一样),MobileNetV2采用逆瓶颈结构,同时引入skip connection提升梯度传播的能力。
该结构的输入输出关系如下,首先使用1x1的卷积得到膨胀特征图,然后使用Depth-wise提取特征,接着使用通道数较少的卷积层提取mainfold of interest。
图示如下:
网络结构如下图,t表示膨胀系数,c为输出通道数,n重复次数,s为步长。(当步长为2或者通道数量变换的时候bootleneck不使用skip connection)
tips:MobileNetV2使用1x1的卷积层代替全连接层。
论文:Searching for MobileNetV3
MobileNetV3是个使用NAS搜索出来的网络结构,它有3个特点:
(1)MobileNetV3的网络结构是NAS搜索出来的;
(2)在bottleneck结构中引入了轻量级注意力模块;
(3)使用swish激活函数而不是relu;
在MobileNetV2的bottleneck基础上,添加SE模块,简单来说就是把[N, C, H, W]特征图池化后经过FC和激活函数,生成[N, C]的特征向量(取值[0, 1]),通过两者相乘使网络自适应选择出重要的特征信息。
参考代码:
class SEModule(nn.Layer):
def __init__(self, channel, reduction=4, name=""):
super(SEModule, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2D(1)
self.conv1 = nn.Conv2D(
in_channels=channel,
out_channels=channel // reduction,
kernel_size=1,
stride=1,
padding=0)
self.conv2 = nn.Conv2D(
in_channels=channel // reduction,
out_channels=channel,
kernel_size=1,
stride=1,
padding=0)
def forward(self, inputs):
outputs = self.avg_pool(inputs)
outputs = self.conv1(outputs)
outputs = F.relu(outputs)
outputs = self.conv2(outputs)
outputs = F.hardsigmoid(outputs)
return paddle.multiply(x=inputs, y=outputs)
引入hard-swish激活函数:
MobileNetV3有large/small 2个版本。
MobileNetV3-Large网络结构如下(SE表示是否使用SE注意力):
MobileNetV3-Small网络结构如下:
MobileNetV3在ImageNet上的实验结果如下图。