MobileNets: Efficient Convolutional Neural Networks for Mobile VisionApplications
论文链接
我们提出了一类用于移动和嵌入式视觉应用的高效模型,称为MobileNets。MobileNet基于一种流线型的架构,该架构使用深度可分离卷积来构建轻量级的深层神经网络。我们引入了两个简单的全局超参数,它们有效地在延迟和准确性之间进行了折衷。这些超参数允许模型构建者根据问题的约束为其应用选择合适大小的模型。我们给出了大量的资源和精度折衷实验,与其他流行的ImageNet分类模型相比,我们显示了更好的性能。然后,我们展示了MobileNets在广泛的应用和用例中的有效性,包括对象检测、细粒度分类、人脸属性和大规模地理定位。
本文描述了一种高效的网络体系结构和一组两个超参数,以构建非常小的、低延迟的模型,这些模型可以很容易地匹配移动和嵌入式视觉应用的设计要求。
在最近的文献中,人们对构建小而有效的神经网络的兴趣与日俱增,例如[16,34,12,36,22]。许多不同的方法通常可以分为压缩预先训练的网络或直接训练小网络。本文提出了一类网络体系结构,它允许模型开发人员专门选择一个与其应用程序的资源限制(延迟、大小)相匹配的小型网络。MobileNet主要专注于优化延迟,但也会打造小型网络。许多关于小型网络的论文只关注大小,而不考虑速度。
先前的网络 | 特点 |
---|---|
MobileNets | 构建深度可分离卷积后在初始模型中使用,以减少最初几层的计算量 |
Flattened networks | 用完全因式分解的卷积构建网络,并展示了分解网络的潜力 |
Factorized Networks | 介绍了类似的因式分解卷积以及拓扑连接的使用 |
Xception network | 演示了如何纵向扩展可分离过滤器 |
Squeezenet | 使用瓶颈方法设计非常小的网络 |
获得小型网络的一种方法是收缩、因式分解或压缩预先训练的网络。在一些论文中基于product quantization(乘积量化)和hashing trick;pruning(剪枝), vector quantization(矢量量化) 和 Huffman coding(霍夫曼编码)的压缩方法已经被提出。此外,已经提出了各种因式分解来加速预先训练的网络[14,20]。另一种训练小型网络的方法是distillation(净化)[9],它使用较大的网络来教导较小的网络。它是对我们的方法的补充,并在第4节的一些用例中进行了介绍。另一种新兴的方法是低位网络。
MobileNet模型基于深度可分离卷积,这是一种因式分解卷积,它将标准卷积分解为深度卷积和称为逐点卷积的1×1卷积。对于MobileNet,深度卷积将单个滤波器应用于每个输入通道。然后,逐点卷积应用1×1卷积来将输出与深度卷积合并。标准卷积在一个步骤中既可对输入进行滤波,又可将其组合成一组新的输出。沿深度可分离的卷积将其分成两层,一层用于滤波,另一层用于合并。这种因式分解的效果是极大地减少了计算量和模型大小。图2显示了如何将标准卷积2(A)分解为深度卷积2(B)和1×1逐点卷积2(C)。
一个标准的卷积层输入为 D F × D F × M D_{F} \times D_{F} \times M DF×DF×M的特征图F要输出一个 D F × D F × N D_{F}\times D_{F}\times N DF×DF×N的特征图G,其中 D F D_{F} DF是方形的输入特征图的空间宽度与高度, M M M是输入的通道数, D G D_{G} DG是方形输出特征图的空间宽度与高度, N N N是输出通道的数量。
一个标准卷积层参数化,尺寸为 D K × D K × M × N D_{K} \times D_{K} \times M \times N DK×DK×M×N的卷积核 K K K,其中 D K DK DK是假设为方形的核的空间维度, M M M是输入通道的数量, N N N是之前定义的输出通道的个数。
标准卷积的计算成本为: D K ⋅ D K ⋅ M ⋅ N ⋅ D F ⋅ D F D_{K} \cdot D_{K} \cdot M \cdot N \cdot D_{F} \cdot D_{F} DK⋅DK⋅M⋅N⋅DF⋅DF
其中计算成本依赖于输入通道的数量 M M M、输出通道的数量 N N N、核大小 D K × D K D_{K} \times D_{K} DK×DK和特征映射大小 D F × D F D_{F} \times D_{F} DF×DF的乘积。MobileNet模型解决了这些术语中之间的交互。首先,它使用深度可分离的卷积来打破输出通道数与核大小之间的相互影响。
标准卷积运算具有基于卷积核的滤波特征和组合特征,以产生新表示的效果。滤波和组合的步骤通过使用被称为深度可分离的分解卷积能够分成两步,大幅减少了计算量。
深度可分卷积由两层组成:深度卷积和逐点卷积。我们使用深度卷积对每个输入通道(输入深度)应用单个滤波器。然后使用点卷积(简单的1×1卷积)来创建深度层的输出的线性组合。MobileNet对两层都使用BatchNorm和RELU非线性。
每个输入通道(输入深度)具有一个滤波器的深度卷积可写为: G ^ k , l , m = ∑ i , j K ^ i , j , m ⋅ F k + i − 1 , l + j − 1 , m \hat{\mathbf{G}}_{k, l, m}=\sum_{i, j} \hat{\mathbf{K}}_{i, j, m} \cdot \mathbf{F}_{k+i-1, l+j-1, m} G^k,l,m=i,j∑K^i,j,m⋅Fk+i−1,l+j−1,m
其中 K ^ \hat K K^是尺寸大小为 D K × D K × M D_{K} \times D_{K} \times M DK×DK×M的深度卷积核, K ^ \hat K K^被应用 F F F的第 m m m个通道对应产生特征图 G G G的第 m m m个通道。
深度卷积的计算成本为: D K ⋅ D K ⋅ M ⋅ D F ⋅ D F D_{K} \cdot D_{K} \cdot M \cdot D_{F} \cdot D_{F} DK⋅DK⋅M⋅DF⋅DF
与标准卷积相比,深度卷积是非常有效的。但是,它只对输入通道滤波,并不组合产生一些新特征。因此需要利用 1 × 1 1\times1 1×1卷积组合产生一些新的特征。
深度可分离卷积的成本: D K ⋅ D K ⋅ M ⋅ D F ⋅ D F + M ⋅ N ⋅ D F ⋅ D F D_{K} \cdot D_{K} \cdot M \cdot D_{F} \cdot D_{F} + M \cdot N \cdot D_{F} \cdot D_{F} DK⋅DK⋅M⋅DF⋅DF+M⋅N⋅DF⋅DF
通过将卷积表示为滤波和合并的两步过程,我们可以减少计算量: D K ⋅ D K ⋅ M ⋅ D F ⋅ D F + M ⋅ N ⋅ D F ⋅ D F D K ⋅ D K ⋅ M ⋅ N ⋅ D F ⋅ D F = 1 N + 1 D K 2 \begin{aligned} &\frac{D_{K} \cdot D_{K} \cdot M \cdot D_{F} \cdot D_{F}+M \cdot N \cdot D_{F} \cdot D_{F}}{D_{K} \cdot D_{K} \cdot M \cdot N \cdot D_{F} \cdot D_{F}}&=\frac{1}{N}+\frac{1}{D_{K}^{2}}\end{aligned} DK⋅DK⋅M⋅N⋅DF⋅DFDK⋅DK⋅M⋅DF⋅DF+M⋅N⋅DF⋅DF=N1+DK21
如第4节所示,MobileNet使用3×3深度可分离卷积,其计算量比标准卷积少8到9倍,而精确度只有很小的降低。空间维度上的因式分解(如[16,31])不会节省太多额外的计算,因为在深度卷积中花费的计算非常少。
MobileNet结构是构建在深度可分离的卷积上的,但第一层除外,它是全卷积。通过如此简单的术语定义网络,我们能够轻松地探索网络拓扑以找到良好的网络。表1定义了MobileNet架构。除了最后的完全连接层为了将输出量送入SoftMax层进行分类没有使用非线性,其余都层均使用了批量归一化和Relu非线性。图3将标准卷积,批量归一化和Relu非线性与具有深度卷积、 1 × 1 1×1 1×1逐点卷积以及每个卷积层之后的批量归一化和Relu非线性的分解层进行对比。下采样在深度卷积和第一层中用跨步卷积处理。最终平均池化会在完全连接的层之前将空间分辨率降低到1。将纵深卷积和逐点卷积计算为单独的层,MobileNet有28层。
仅仅用少量的Mult-Adds来定义网络是不够的。同样重要的是要确保这些操作可以有效地实现其功能。例如,非结构化的稀疏矩阵操作通常不会比密集矩阵操作快,直到达到非常高的稀疏程度。我们的模型结构将几乎所有的计算放在密集的1×1卷积中。这可以通过高度优化的通用矩阵乘法(GEMM)函数来实现。卷积通常由GEMM实现,但需要在内存中调用im2col进行初始重新排序,以便将其映射到GEMM。例如,这种方法被用于流行的Coffe框架[15]。1×1卷积不需要在内存中重新排序,可以直接使用GEMM实现,GEMM是最优化的数值线性代数算法之一。MobileNet在 1 × 1 1×1 1×1卷积中花费了95%的计算时间,也有75%的参数,如表2所示。几乎所有的附加参数都在完全连接层中。
MobileNet模型在TensorFlow[1]中使用RMSprop[33]进行训练,具有类似于InceptionV3[31]的异步梯度下降。然而,与训练大模型相反,我们使用较少的正则化和数据增强技术,因为小模型的过拟合问题较少。此外,我们发现在深度滤波器上放置非常少的或没有权重衰减(L2正则化)是很重要的,因为它们的参数太少了。对于下一节中的ImageNet基准测试,所有模型都使用相同的训练参数进行训练,而不考虑模型的大小。
尽管基本的MobileNet体系结构已经很小并且延迟很短,但是很多情况下,特定的用例或应用程序可能要求模型更小,更快。为了构造这些较小且计算量较小的模型,我们引入了一个非常简单的参数 α α α,称为宽度乘数。宽度乘数 α α α的作用是使每一层的网络均匀变薄。对于给定的层和宽度乘子 α α α,输入信道数 M M M变为 α M αM αM,输出信道数 N N N变为 α N αN αN。具有宽度乘数α的深度可分离卷积的计算成本为: D K ⋅ D K ⋅ α M ⋅ D F ⋅ D F + α M ⋅ α N ⋅ D F ⋅ D F D_{K} \cdot D_{K} \cdotαM \cdot D_{F} \cdot D_{F} + αM \cdot αN \cdot D_{F} \cdot D_{F} DK⋅DK⋅αM⋅DF⋅DF+αM⋅αN⋅DF⋅DF
其中, α ∈ ( 0 , 1 ] α∈(0,1] α∈(0,1]的典型设置为1、0.75、0.5和0.25。 α = 1 α= 1 α=1是基准MobileNet, α < 1 α<1 α<1是简化的MobileNets。宽度乘数具有降低计算成本和参数数量大约为 α 2 α^2 α2。宽度乘数可以应用于任何模型结构,以合理的精度,等待时间和尺寸折衷来定义新的较小模型。它用于定义新的精简结构,需要从头开始进行培训。
减少神经网络计算成本的第二个超参数是分辨率乘数 ρ ρ ρ。我们将其应用于输入图像,每一层的内部表示随后被相同的乘法器减少,实际上我们通过设置输入分辨率隐式地设置了ρ。现在,我们可以将网络核心层的计算成本表示为具有宽度乘数α和分辨率乘数ρ的深度可分离卷积: D K ⋅ D K ⋅ α M ⋅ ρ D F ⋅ ρ D F + α M ⋅ α N ⋅ ρ D F ⋅ ρ D F D_{K} \cdot D_{K} \cdot \alpha M \cdot \rho D_{F} \cdot \rho D_{F}+\alpha M \cdot \alpha N \cdot \rho D_{F} \cdot \rho D_{F} DK⋅DK⋅αM⋅ρDF⋅ρDF+αM⋅αN⋅ρDF⋅ρDF
其中 ρ ∈ ( 0 , 1 ] ρ∈(0,1] ρ∈(0,1]通常是隐式设置的,因此网络的输入分辨率为224、192、160或128。 ρ = 1 ρ=1 ρ=1是基准MobileNet,而 ρ < 1 ρ<1 ρ<1是简化的计算MobileNets。将计算成本降低 ρ 2 ρ^2 ρ2的效果。
作为示例,我们可以查看MobileNet中的典型层,并了解深度可分离卷积,宽度乘数和分辨率乘数如何减少成本和参数。表3显示了将体系结构收缩方法依次应用于该层时该层的参数计算和数量。第一行显示了完整卷积层的Mult-Adds和参数,输入特征图的大小为 14 × 14 × 512 14×14×512 14×14×512,内核 K K K的大小为3×3×512×512。我们将在下一部分中详细介绍在资源和准确性之间进行权衡。
首先,我们给出了使用深度可分离卷积的MobileNet与使用完全卷积建立的模型相比的结果。在表4中我们看到,使用深度可分离的卷积与完全卷积相比,ImageNet上的精度仅降低了 1 % 1% 1%,可以大大节省Mult-adds和参数。
接下来,我们将显示使用宽度乘数的较薄模型与使用较少层的较浅模型进行比较的结果。为了使MobileNet更浅,去掉了表1中特征尺寸为 14 × 14 × 512 14×14×512 14×14×512的 5 5 5层可分离过滤器。表5显示,在类似的计算和参数数量下,使移动网络变薄比使其变浅要好3%。
表6显示了使用宽度乘数 α α α缩小MobileNet网络架构的精度、计算和尺寸权衡。精确度会平滑下降,直到体系结构在 α = 0.25 α=0.25 α=0.25时变得太小。
表7显示了通过减少输入分辨率MobileNet,训练的不同分辨率乘法器的精度、计算和尺寸权衡。精度在分辨率上会平稳下降。
图4显示了由宽度乘数 α ∈ 1 , 0.75 , 0.5 , 0.25 α∈{1,0.75,0.5,0.25} α∈1,0.75,0.5,0.25和分辨率乘数 224 , 192 , 160 , 128 {224,192,160,128} 224,192,160,128的叉积构成的16个模型的Imagenet精度和计算之间的权衡。当模型在α=0.25时变得非常小时,结果是对数线性的跳跃。
图5显示了由宽度乘数 α ∈ 1 , 0.75 , 0.5 , 0.25 α∈{1,0.75,0.5,0.25} α∈1,0.75,0.5,0.25和分辨率乘数 224 , 192 , 160 , 128 {224,192,160,128} 224,192,160,128的叉积制成的16个模型的Imagenet精度和参数数量之间的权衡。
表8将完整的MobileNet与原始的GoogLeNet[30]和VGG16[27]进行了比较。MobileNet的精确度几乎与VGG16相当,但体积小32倍,计算密集度低27倍。它比GoogLeNet更准确,而且计算量更小,减少了2.5倍以上的计算量。
表9比较了宽度乘数 α = 0.5 α=0.5 α=0.5且分辨率降低为160×160的精简的MobileNet比AlexNet[19]好4%,而体积比AlexNet小45倍,计算量比AlexNet少9.4倍。与Squeezenet[12]相比,在同样大小的情况下,它也比Squeezenet[12]提高了4%,而计算量减少了22倍。
我们在Stanford Dogs数据集上训练MobileNet进行细粒度识别[17]。我们扩展了[18]的方法,从网络上收集了比[18]更大而且噪音更大的训练集。我们使用有噪声的网络数据来预先训练一个细粒度的狗识别模型,然后在Stanford Dogs的训练集上对该模型进行微调。Stanford Dogs测试集的结果如表10所示。MobileNet几乎可以在极大地减少计算量和大小的情况下达到[18]的最先进结果。
PlaNet [35]负责确定将照片拍摄到哪里作为分类问题。该方法将地球划分为一个由地理单元组成的网格,作为目标类,并在数百万张地理标记照片上训练一个卷积神经网络。Planet已经被证明能够成功地定位了大量的照片,并且比解决相同任务的Im2GPS[6,7]的性能更好。
我们使用MobileNet架构在相同的数据上重新训练PlaNet。而基于感知V3架构[31]的完整PlaNet模型有5200万个参数和574亿个多重加法。MobileNet模型只有1300万个参数,通常是300万个参数,最后一层为1000万个参数,58万mult-adds。如表11所示,MobileNet版本虽然更紧凑,但与PlaNet相比,性能仅略有下降。此外,它的性能仍然大大优于Im2GPS。
MobileNet的另一个用例是压缩具有未知或深奥训练过程的大型系统。在面部属性分类任务中,我们展示了MobileNet和精馏之间的协同关系[9],这是一种深度网络的知识转移技术。我们试图用7500万个参数和16亿个Mult-Adds来减少一个大型的人脸属性分类器。分类器是在类似于YFCC100M[32]的多属性数据集上训练的。
MobileNet也可以作为现代目标检测系统的有效基础网络。我们根据最近赢得2016年COCO挑战赛的研究报告了MobileNet在COCO数据上进行目标检测训练的结果[10]。在表13中,在Faster-RCNN[23]和SSD[21]框架下,MobileNet与VGG和Inception V2[13]进行了比较。在我们的实验中,SSD的输入分辨率为300(SSD 300),Faster-RCNN的输入分辨率为300和600(Faster-RCNN 300,Faster-RCNN 600)。更快的RCNN模型评估每个图像300个RPN候选框。模型在COCO 训练+验证集上训练,不包括8k minival图像,并在minival上进行评估。对于这两个框架,MobileNet在计算复杂度更低和模型更小小的情况下取得了与其他网络相当的结果。
FaceNet模型是最先进的人脸识别模型[25]。它构建面嵌入是基于triplet loss。为了建立一个移动FaceNet模型,我们使用蒸馏来训练,通过最小化FaceNet和MobileNet输出在训练数据上的平方差。非常小的MobileNet模型的结果见表14。
提出了一种新的基于可分离卷积的MobileNets模型结构。我们研究了一些导致有效模型的重要设计决策。然后,我们展示了如何使用宽度乘数和分辨率乘数构建更小、更快的mobilenet,通过权衡一定的精度来减少模型尺寸和延迟。然后,我们将不同的MobileNets与流行的模型进行了比较,这些模型展示了优越的尺寸,速度和准确度特征。最后,我们演示了MobileNet在应用于各种任务时的有效性。为了帮助进一步采用和探索MobileNets,我们计划基于TensorFlow框架发布模型。
import time
import torch
from torch import nn,optim
import torch.nn.functional as F
import d2lzh_pytorch as d2l
class MobileNet_v1(nn.Module):
def __init__(self,in_chanels,out_chanels,stride=1):
super(MobileNet_v1,self).__init__()
# 深度分离卷积核,3 x 3层
self.conv1 = nn.Conv2d(in_chanels,in_chanels,kernel_size=3,padding=1,stride=stride,groups=in_chanels,bias=False)
# 点卷核,1 x 1层
self.conv2 = nn.Conv2d(in_chanels,out_chanels,kernel_size=1,padding=0,bias=False)
#进行batch_normal
self.bn1 = nn.BatchNorm2d(in_chanels)
self.bn2 = nn.BatchNorm2d(out_chanels)
def forward(self,X):
Y = F.relu(self.bn1(self.conv1(X)),inplace=True)
Z = self.bn2(self.conv2(Y))
return F.relu(Z,inplace=True)
#检验模型
blk = MobileNet_v1(3,32)
X = torch.rand((1,3,224,224))
blk(X).shape
torch.Size([1, 32, 224, 224])
net = nn.Sequential(
nn.Conv2d(3,32,3,stride=2,padding=1,bias = False),
nn.BatchNorm2d(32),
nn.ReLU(),
)
net.add_module("Mobilenet_bolock1",MobileNet_v1(32,64))
net.add_module("Mobilenet_bolock2",MobileNet_v1(64,128,2))
net.add_module("Mobilenet_bolock3",MobileNet_v1(128,128))
net.add_module("Mobilenet_bolock4",MobileNet_v1(128,256,2))
net.add_module("Mobilenet_bolock5",MobileNet_v1(256,256))
net.add_module("Mobilenet_bolock6",MobileNet_v1(256,512,2))
net.add_module("Mobilenet_bolock7",MobileNet_v1(512,512))
net.add_module("Mobilenet_bolock8",MobileNet_v1(512,512))
net.add_module("Mobilenet_bolock9",MobileNet_v1(512,512))
net.add_module("Mobilenet_bolock10",MobileNet_v1(512,512))
net.add_module("Mobilenet_bolock11",MobileNet_v1(512,512))
net.add_module("Mobilenet_bolock12",MobileNet_v1(512,1024,2))
net.add_module("Mobilenet_bolock13",MobileNet_v1(1024,1024))
net.add_module("avg pool",nn.AvgPool2d(7))
net.add_module("fc",nn.Sequential(d2l.FlattenLayer(),nn.Linear(1024,1000)))
#检验模型
x = torch.rand(1,3,224,224)
for name,layer in net.named_children():
x = layer(x)
print(name,"output shape:\t",x.shape)
0 output shape: torch.Size([1, 32, 112, 112])
1 output shape: torch.Size([1, 32, 112, 112])
2 output shape: torch.Size([1, 32, 112, 112])
Mobilenet_bolock1 output shape: torch.Size([1, 64, 112, 112])
Mobilenet_bolock2 output shape: torch.Size([1, 128, 56, 56])
Mobilenet_bolock3 output shape: torch.Size([1, 128, 56, 56])
Mobilenet_bolock4 output shape: torch.Size([1, 256, 28, 28])
Mobilenet_bolock5 output shape: torch.Size([1, 256, 28, 28])
Mobilenet_bolock6 output shape: torch.Size([1, 512, 14, 14])
Mobilenet_bolock7 output shape: torch.Size([1, 512, 14, 14])
Mobilenet_bolock8 output shape: torch.Size([1, 512, 14, 14])
Mobilenet_bolock9 output shape: torch.Size([1, 512, 14, 14])
Mobilenet_bolock10 output shape: torch.Size([1, 512, 14, 14])
Mobilenet_bolock11 output shape: torch.Size([1, 512, 14, 14])
Mobilenet_bolock12 output shape: torch.Size([1, 1024, 7, 7])
Mobilenet_bolock13 output shape: torch.Size([1, 1024, 7, 7])
avg poll output shape: torch.Size([1, 1024, 1, 1])
fc output shape: torch.Size([1, 1000])
论文链接