MobileNet 系列讲解

MobileNet 作为轻量级网络的代表,使得 CNN 轻量化和移动端的部署成为可能。MobileNet 目前有三个版本,分别是 MobileNet v1, MobileNet v2 和 MobileNet v3.

MobileNet-v1

卷积神经网络CNN总结(五)

简单来说 MobileNet v1 就是将常规卷积替换成深度可分离卷积 (depthwise separable convolution) 的 VGG 网络。

卷积神经网络CNN总结(五)

可以看到,VGG的卷积块就是一个常规33卷积和一个BN、一个ReLU激活层。MobileNet v1则是一个33深度可分离卷积和一个1*1卷积,后面分别跟着一个BN和ReLU层。MobileNet v1的ReLU指的是ReLU6,区别于ReLU的是对激活输出做了一个clip,使得最大最输出值不超过6,这么做的目的是为了防止过大的激活输出值带来较大的精度损失。

那么为什么是深度可分离卷积呢?

从维度的角度看,卷积核可以看成是一个空间维(宽和高)和通道维的组合,而卷积操作则可以视为空间相关性和通道相关性的联合映射。从inception的1*1卷积来看,卷积中的空间相关性和通道相关性是可以解耦的,将它们分开进行映射,可能会达到更好的效果。

深度可分离卷积是在11卷积基础上的一种创新。主要包括两个部分:深度卷积和11卷积。深度卷积的目的在于对输入的每一个通道都单独使用一个卷积核对其进行卷积,也就是通道分离后再组合。1*1卷积的目的则在于加强深度。下面以一个例子来看一下深度可分离卷积。

假设我们用128个$333$的滤波器对一个$773$的输入进行卷积,可得到$55128$的输出。如下图所示:

卷积神经网络CNN总结(五)

其计算量为 5512833*3=8640

现在看如何使用深度可分离卷积来实现同样的结果。深度可分离卷积的第一步是深度卷积(Depth-Wise)。这里的深度卷积,就是分别用3个331的滤波器对输入的3个通道分别做卷积,也就是说要做3次卷积,每次卷积都有一个551的输出,组合在一起便是553的输出。

现在为了拓展深度达到128,我们需要执行深度可分离卷积的第二步:1x1卷积(Point-Wise)。现在我们用128个113的滤波器对553进行卷积,就可以得到55128的输出。完整过程如下图所示:

卷积神经网络CNN总结(五)

那么我们来看一下深度可分离卷积的计算量如何。第一步深度卷积的计算量:5513313=675。第二步1x1卷积的计算量:5512811*3=9600,合计计算量为10275次。可见,相同的卷积计算输出,深度可分离卷积要比常规卷积节省12倍的计算成本。所以深度可分离卷积是MobileNet v1能够轻量化的关键原因。

MobileNet v1完整网络结构如下图所示。

卷积神经网络CNN总结(五)

MobileNet v1与GoogleNet和VGG 16在ImageNet上的效果对比,如下表所示:

卷积神经网络CNN总结(五)

可以看到,MobileNet v1相比与VGG 16精度损失不超过一个点的情况下,参数量小了32倍之多!MobileNet v1在速度和大小上的优势是显而易见的。

MobileNet-v2

MobileNet v2是在v1基础上的改进与优化版本。MobileNet v2论文题目为MobileNetV2: Inverted Residuals and Linear Bottlenecks,由谷歌发表于2018年CVPR上。

img

MobileNet v1的特色就是深度可分离卷积,但研究人员发现深度可分离卷积中有大量卷积核为0,即有很多卷积核没有参与实际计算。是什么原因造成的呢?v2的作者发现是ReLU激活函数的问题,认为ReLU这个激活函数,

既然如此,v2的解决方案也很简单,就是直接将ReLU6激活换成线性激活函数,当然也不是全都换,只是将最后一层的ReLU换成线性函数。具体到v2网络中就是将最后的Point-Wise卷积的ReLU6都换成线性函数。v2给这个操作命名为linear bottleneck,这也是v2网络的第一个关键点

深度卷积(Depth-Wise)本身没有改变通道的作用,比如本文前例中的深度可分离卷积的例子,在前一半的深度卷积操作中,输入是3个通道,输出还是3个通道。所以为了能让深度卷积能在高维上工作,v2提出在深度卷积之前加一个扩充通道的卷积操作,什么操作能给通道升维呢?当然是1*1卷积了。

img

这种在深度卷积之前扩充通道的操作在v2中被称作Expansion layer。这也是v2网络的第二个关键点

img

从图中可以看到,ResNet是先0.25倍降维,然后标准3*3卷积,再升维,而MobileNet v2则是先6倍升维,然后深度可分离卷积,最后再降维。更形象一点我们可以这么画:

img

倒残差。

Inverted resdiual之后就组成了MobileNet v2的block,如下图所示。

img

img

可以看到,输入经过一个常规卷积之后,v2网络紧接着加了7个bottleneck block层,然后再两个11卷积和一个77的平均池化的组合操作。

MobileNet-v3

特点可以归结为

  • 使用NAS神经架构搜索确定网络结构

  • 在v2的block基础上引入Squeeze and Excitation结构

  • 使用h-swish激活函数

  • 对v2网络尾部结构进行改进

NAS (neural architecture search)相关介绍

CNN 有很多经典架构,可以分为认为设计和网络搜索两部分。早期的 Alexnet、VGG、Inception 到 resnet、Mobilnet,都包含这作者对于网络架构的见解。网络搜索比如说 EfficientNet。

随着时代的改变,虽然pooling layer时常被较大stride的convolution取代,global average pooling与1x1 convolution也时不时代替了FC layer,这个大方向依然是大致正确的。

(这个是需要积累的)

builing block

这个是常常被使用的术语,指的是不断重复使用的小网络组合。比如 resnet 中的 residual block, residual bottleneck block 或者是 mobileNet 中的depthwise separable convolution block

在主框架的情况下,一般常调整的项目就是以下三种:

  • 深度 depth:堆叠的 building block 或者 convolution layer 的数量
  • 宽度 width:表示 building block或者 convolution layer 输出 feature map 的宽度(channels 或者 filters 数量)
  • 解析度 resolution:表示改 building block 或者convolution layer 输出 feature map的解析度(feature map 的长和宽)

EfficentNet论文提供单独增加深度、宽度与解析度上的实验。从实验上可以看出,单独增强其中一项对效能的提升都是有效的,但是很快这个效果就会饱和。

img

Compound Scaling

基于单一强化的实验,EfficientNet的作者认为应该要一起考虑强化深度、宽度与解析度三项。然而,在一定的运算量设定下,如何决定调整这三项之间的调整比例则是一个开放的问题。

以上是基本的概念,现在来说主角 NAS

虽然号称神经网路的自动搜寻,但NAS也不是无敌的万事通,NAS的实作一般需要定义三个元素:

  1. Search Space: 定义可以选择的网路基本元素(如convolution、batch normalization)、与可以调整的内容(如kernel size、filter number)。
  2. Search strategy: 定义搜寻的方法,如reinforcement learning是其中一个常见的方法。
  3. Performance estimation: 定义如何评估一个架构的好坏,如准确度、运算量等等。

EfficientNet [7]是可以说是目前(2020年) mobile (使用CPU计算)最强的网路架构。EfficientNet沿用MnasNet [8]的search space,但将运算资源的估测从latency改成FLOPs,即对于某个网路m、目标运算量T,使用一个hyperparameterw控制accuracy与FLOPs的trade-of,最佳化Accuracy(m)*[FLOPs(m)/T]^w

EfficientNet论文找出了一个base架构EfficentNet-B0后,依照compound scaling的原则,假设运算资源为两倍,找出了最佳的scaling parameters ( α=1.2, β=1.1, γ=1.15),依照这个scaling方法*[补充3]*,依序推理更大的架构EfficentNet-B1到EfficentNet-B7。是现在(2020年)最强也最高效的网路架构之一。

Handcraft Design with Insights

在一般的情况下,人为设计网路的流程大概是这样:先从一个大略的网路概念假设一个网路可调整范围(design space,以NAS的术语是search space),我们会在这个空间进行大量的实验后,找到一些容易带来正效益的方向。这时候我们会依照这个方向继续进行实验,也就等同于收敛到一个更小的design space。而这样递回地进行,就像下图从A走到B再走到C的过程。

img

回想一下NAS的三大元素:search space、search strategy、performance evaluation。其实人为设计与NAS根本没什么两样,只是search strategy是依照着我们自己本身的知识在进行。但这就是导致结果最不一样的地方,NAS以performance为最佳依据,擅长找到那一个最强的模型。而人为设计的过程则是观察performance,却也同时依照自己过往知识与经验的累积、每个参数代表的意义、每个增加的模块效果等等推测方向,因此找出来的通常一种方向并且带有某些insight

我认为现阶段的NAS的许多设定(比如说search space)还是靠着人的智慧在设定,这代表NAS还是必须先借镜许多handcraft的insight。另一方面,人类也会试图从NAS找出来的架构中得到一些insight。因此,NAS与handcraft目前可以说是相辅相成的。

NAS的优势在于找出对于任务最优势的架构,然而极强的目的性也带来了泛化性的不确定(会不会找出over-fitting的架构) 。这也是为什么EfficientNet论文除了证明其架构在ImageNet上的强大,还额外花了一些篇幅展示他的transfer到其他classification dataset的能力。不过,即使transfer到其他同dataset可行,transfer到其他任务或许又是另一个问题。

事实上,EfficientNet在其他视觉任务中,不论是object detection或是semantic segmentation中已经展现了强大的能力[10],泛化能力乍看无懈可击,不过这个评比是建立在"同量级的FLOPs"最优先的基准下。

NAS的另一个问题就是可解释性比较差。比如说RegNet在sample并演化架构的过程中发现了渐渐增加的网路宽度是好的设计,然而EfficientNet一开始就来了一个宽度从32到16的压缩。虽然EfficentNet结果就是如此优秀,这样的一个难解释的设计却也增加了理解与修改的困扰。

至于EfficientNet与RegNet孰优孰劣,大概也没有个绝对。从论文数据来看,低运算量的模型还是EfficientNet有优势,但由于EfficientNet的depthwise seperable convolution与activation数量对GPU运算较不友善,在有GPU的情况RegNet的运算速度可以比同样FLOPs数的EfficientNet快上数倍。

第二个改进措施就是在v2基础上引入squeeze and excitation结构,熟悉SENet的读者应该知道,这是一个对通道之间相互依赖关系进行建模的操作。在v2基础上,v3网络的block如下图所示。

img

第三个改进点是使用了h-swish激活函数。h-swish激活函数是基于swish的改进,swish激活函数表达式如下:

$$ swish(x) = x * sigmoid(\beta x) $$

swish激活函数图像在β取0.1、1.0和10.0时如下图所示:

img

swish激活函数在一系列深度卷积网络上都对效果有显著提升,MobileNet也不例外,但是v3认为,作为一个轻量化的网络,swish激活虽然能带来精度提升,但在移动设备上会有速度损失。所以在swish函数的基础上,v3对其进行了改进,提出了h-swish激活函数。

h-swish的基本想法是用一个近似函数来逼近swish函数,让swish函数变得不那么光滑(hard),基于MobileNet v1和v2的经验,v3还是选择了ReLU6。变换逻辑如下图所示。

img

swish和h-swish函数对比图像:

img

可以将h-swish视为swish的低精度化模式,相较于swish,h-swish能够保持相同精度的条件下减少时间和计算量的开销。

总结

最后一句话对MobileNet系列做个简单的总结,MobileNet v1就是加了深度可分离卷积的VGG;MobileNet v2则是在v1基础上加了Linear激活、Expansion layer和Inverted residual三大关键操作;而v3则是在v2基础上引入NAS,并且加入Squeeze and Excitation结构、h-swish激活和网络尾部优化等改进措施。

实践

实际程序运行中,MobileNet往往起不到论文所述“加速”的作用,相反,使用了MobileNet后,模型的计算速度反而变慢了。

而在速度方面,经过大量实验,我发现在算力足够的GPU平台上,MobileNet不会带来任何速度上的提升(有时甚至是下降的),然而在计算能力有限的平台上,MobileNet能让速度提升三倍以上。

注:这个速度的计算方法是随机生成一个224x224x3的tensor,送入网络进行前向计算,多次计算计时并取平均值。

img

解释:

深度可分离卷积将一个标准卷积分割成两个卷积(逐深度、逐点),因此减少了参数量,对应减少了计算量。但是可以发现一个有趣的事实:深度可分离卷积总计算量变小了,但深度可分离卷积的层数变多了

GPU是并行处理大规模数据(矩阵内积)的运算平台,而CPU倾向于对数据串行计算。所以当GPU 的显存足够大的时候(能够放下整个网络),因为每一层都可以并行一次处理,所有总运算时间的主导因素是网络的层数。而对于缺乏并行能力的CPU,总的运算时间的主导因素是总计算量

参考文献

轻量化 CNN 网络 MobileNet 系列详解

MobileNet 详解深度可分离卷积,它真的又好又快吗?

Convolutional Neural Network的设计论:NAS (EfficientNet) vs Handcraft (RegNet)

RegNet

论文中衡量模型的常用指标:

FLOPS:(注意全部是大写)是floating point operations per second的缩写,意指每秒浮点运算次数,理解为计算速度。是一个衡量硬件性能的指标

FLOPs:(注意 s 是小写)是 floating point operations 的缩写(s表示复数),意指浮点运算数,理解为计算量。可以用来衡量算法/ 模型的复杂度。

parameters:(参数量)

但是 RegNet 中并不这样认为:

Complexity analysis

除了FLOPs和参数,作者分析了所有卷积层的输出feature map的尺寸,将其定义为activations,用于度量网络的复杂度,在图12的左上角列出了常见卷积算子的复杂性度量。虽然activations不是衡量网络复杂性的通用标准,但activations可能会严重影响内存受限硬件加速器(例如GPU、TPU)上的运行时间,在图12(上)可以看到,activations与推理时间的正相关性比FLOPs更强。在图12(下)中,观察到对于总体中最好的模型,activations随FLOPs的平方根增加,参数量随FLOPs线性增加,并且推理时间最好使用FLOPs的线性和平方根项联合建模(即图12(下右)中的式子24f+6.0⋅f),因为它同时依赖于FLOPs和activations

image-20200823202441320

efficientnet 被“吐槽”的点

  • transfer learning 困难,efficientnet 中古怪的超参数
  • efficientnet 很低的 FLOPs 却伴随着较高的推理时间。比如B2 版本的 FLOPs 不到 ResNet50 的一半,推理速度却是 ResNet50 的两倍

大部分时候,GPU的算力瓶颈在于访存带宽。同样计算量,访存带宽差异巨大。EfficientNet 中使用了depthwise Conv(低 FlOPs 但高数据读写量),所以大量的时间被浪费在从显存中读写数据上,GPU 的算力没有得到“充分利用”

以下是一个例子(不要求会算,但需要记住结论)

1
2
3
4
5
6
然后为了达到同样的FLOPs,我们假设另一个大小为56*56*10000的feature,经过一个kernel size为3x3的depthwise卷积layer,卷积layer的输出channel是10000。其FLOPs计算过程如下:

一个卷积kernel的大小为:3*3*1,与feature上一个同等大小的blob进行卷积,总共有3*3次乘法。然后10000个channel通道,每个通道互相独立,对应着10000个不同的卷积kernel,所以重复这一卷积过程10000次。同时在feature的空间位置上逐元素重复,总的FLOPs为:3*3*10000*56*56。卷积核参数总量为:3*3*1*10000。
可以看到,两个layer的FLOPs和参数量完全相同。但是推理速度方面,depthwise卷积要远远慢于普通卷积。其原因就是访存数据量的不同:

由于卷积计算本身已经是flatten的,不需要考虑重复读取问题,那么总共读取的数据量就是feature的大小加上卷积核weight的大小,对于普通卷积来说,总读取数据量为:100*56*56 + 3*3*100*100 = 4.0e+05。类似的,depthwise卷积读取的数据总量为:56*56*10000 + 3*3*10000 = 3.1e+07。

可以看到,在同等FLOPs的情况下,depthwise卷积对应的feature size比普通卷积大的多,受制于GPU访存带宽,过高的数据读取与写入量就成为了限制推理速度的瓶颈。

Paper: Designing Network Design Spaces

GitHub:

良好的RegNet模型还适用于广泛的计算环境,包括ResNet和ResNeXT都不太适应的低计算环境。

当 flops 较低时,efficientNet 还有优势,但是随着 flops 的增大,RegNetX 和 RegNetY 逐渐发力。

在何凯明团队中,研究人员提出,设计一个不受限制的初始设计空间的逐步简化版本。这一过程,被称为设计空间设计(design space design)

在设计过程的每个步骤中,输入都是初始设计空间,输出则是更简单、或性能更好的模型的精简模型。

通过对模型进行采样,并检查其误差分布,即可表征设计空间的质量。

研究人员设计的初始设计空间是 AnyNet

解耦:接触耦合,降低耦合度即可以理解为解耦。

前言

类似efficientnet 这样的 NAS 是 focus 在“个体估计” 层面。即在一个搜索空间里,每次采样和评估都是以个体为单位,最终目的是找到一个或几个最好的结构。这样做的问题

  • 搜索空间先验性太强
  • 搜索算法与搜索空间的耦合
  • 可解释性不足,可迁移性 / 泛化能力不足

本文的创新点 focus 在“群体估计”, design space design。做法如下:为了得到一个空间内模型的性能分布,我们在该空间中抽样并训练n个模型,为了提高效率,我们只抽样大小为400MF(即400M FLOPs)的模型样本,每个样本在ImageNet数据集上训练10个epochs。

作者这里假设,由于抽样大量的样本,每个样本训练10个epoch的后的群体性能足以刻画该空间的质量。

网络深度的讨论

使用上述这些发现,我们可以对RegNetX设计空间进一步微调,首先基于图11(上),设置b=1,d≤40,𝑤𝑚wm≥2 。然后基于图12(下),对参数量和activations进行约束。这样就能产生快速的、低参数量的、low-memory且不影响精度的模型。在图13中,我们对比了 𝑅𝑒𝑔𝑁𝑒𝑡𝑋RegNetX有这些约束-C没有这些约束-U下的表现,可以发现在所有FLOPs下,有约束的性能比没有约束的更好。因此在下面的实验结果小节都使用有约束的版本,然后更进一步的限制网络深度12≤d≤28(在附录D中有解释)。

image-20200823202511224

AnyNetX 设计空间

将初始的 AnyNetX 称作 AnyNetXA,开始进行“A→B→C→D→E”的优化过程。

AnyNetXA

为了清晰起见,我们将最初的、不受约束的AnyNetX设计空间称为AnyNetXA。

AnyNetXB

AnyNetXC

AnyNetXD

AnyNetXE

从上往下,限制是逐步增加的

最后,作者将block X和Squeeze-and-Excitation (SE)模块进行结合,得到了新的设计空间 𝑅𝑒𝑔𝑁𝑒𝑡𝑌RegNetY 。在图14(右),发现 𝑅𝑒𝑔𝑁𝑒𝑡𝑌RegNetY 性能提升比较明显。

Squeeze-and-Excitation Networks(SENet)是由自动驾驶公司Momenta在2017年公布的一种全新的图像识别结构,它通过对特征通道间的相关性进行建模,把重要的特征进行强化来提升准确率。这个结构是2017 ILSVR竞赛的冠军,top5的错误率达到了2.251%,比2016年的第一名还要低25%,可谓提升巨大。

评论

Designing Network Design Spaces

经过我自己的实验。同样的epoch和batch size下,RegNetX-8.0GF只占用9G显存,9个半小时单卡就训练完了。但是efficientnet-b4占用双卡,显存占满,需要训练21个小时。最终两者的精度基本一致,但是推理时间RegNetX-8.0GF(15.65)只有efficientnet-b4(29.17)的一半。下面对该论文进行详细介绍。

论文中的一些操作还是有争议的

10 epoch 争议比较大,模型的表现跟 epoch 还是有很大的关系,数字 10 出现得不是那么有依据

其他

facebook 中 nas 的其他作品,FBNet:https://aijishu.com/a/1060000000137736

对应的github: https://github.com/facebookresearch/mobile-vision