深度学习模型结构那么多,部署到移动端该选哪一个?Matthijs Hollemans 是iOS深度学习专家,移动端部署工程化踩过不少坑的看他的文章应该很有共鸣,如算子不支持,FLOPS 误导性等等问题。这些经验其实不仅仅适用于iOS,Android和Linux平台也是共通的。另外虽然benchmark是分类,但backbone性能对于目标检测,语义分割等任务也很有参考价值。超长预警!!
New mobile neural network architectures by Matthijs Hollemans
https://machinethink.net/blog/mobile-architectures/
在过去的18个月里,新推出了很多专门用于移动设备和边缘设备的新神经网络结构。
几乎每个人都已经意识到,大型模型(如VGG16或ResNet-50)在小型设备上不是一个好主意。
我以前写过有关MobileNet v1和v2的文章,并在很多客户项目中使用了这些模型。但这是2020年了,新出炉了不少模型!
在此文中,我们将研究很多新的神经网络设计,并进行一些速度测试以了解它们有多快。
首先,我们回顾一些较旧的结构:
- SqueezeNet
- MobileNet v1
- MobileNet v2
然后我们看一下新的:
- MnasNet
- MobileNet v3
- BlazeFace
- TinyYOLO / Darknet
- SqueezeNext
- ShuffleNet
- CondenseNet
- ESPNet
- DiCENet
- FBNet和ChamNet
- GhostNet
- MixNet
- EfficientNet
我有可能漏了一些结构。发现了这里未涵盖的有趣结构?请告诉我,我将其添加到博客文章中。
注意:由于我专注于iOS,因此我们将使用Core ML和iPhone进行速度测试。Android上有可能大不一样!
你为什么要关注呢?
将神经网络放入您的应用程序时,最好使用快速高效的模型结构。特别是如果您想经常进行预测,例如实时视频。
诸如ResNet-50之类的神经网络(这是研究论文中使用的典型骨干模型)功率过高,因此不适合实时使用。
当然,与绝大多数工程技术一样,需要权衡取舍:
- 通常,模型越大,结果越好。但同时运行速度越慢,消耗的能量就越多。大型模型会迅速使手机变热并耗尽电池电量。那可不是很好的用户体验。
- 较小的模型运行速度更快,并且消耗的电池电量更少,但通常得出的结果不太准确。
作为移动ML从业人员,您的工作是找到一个既足够快但又能提供足够好的结果的模型结构。
以前,我通常会推荐MobileNet v1或v2。但是现在有更多选择,所以让我们看看是否可以做得更好。
使问题复杂化的是,某些模型结构在GPU上工作得更好,而其它模型结构在神经引擎(ANE)上更好:
- 如果您仅针对较新的设备(iPhone XS及更高型号),那么用可以利用ANE的神经网络设计是明智之选。
- 相反,如果您主要针对的是iPhone X和更早型号,则选择一个在GPU上运行良好的模型很有意义,因为这些较旧的设备没有神经引擎(X有ANE,但Core ML无法使用它)。
- 并非所有模型都可以(完全)在ANE上运行。目前,神经引擎并不支持Core ML的所有层类型。
我希望通过这篇文章可以帮助大家更轻松地选择合适的结构。
注意:如果您的应用仅偶尔使用神经网络,则可以用更大的模型(例如ResNet-50)。该模型可能需要一秒钟左右的时间来计算结果,但在这种情况下还算可以接受。但是,请记住,大型模型还会使app包更大。由于其中一些新结构可以与较大模型的质量相媲美,因此切换到较小模型至少可以节省一些空间(例如,ResNet-50给app增加了约100 MB)。
骨干
我们将介绍的大多数模型都是图像分类器。通常,这些模型在ImageNet上进行训练,我们可以通过ImageNet测试集上的分类准确率来判断它们的优劣。
但是,这并不是我们对这些模型感兴趣的主要原因——毕竟,没有多少app需要ImageNet分类器......
我们将评估这些模型作为特征提取器(作为执行某种计算机视觉任务的大型神经网络的一部分)的有用性。这可以是分类或其它任务,例如目标检测,姿态估计,分割等。
在大多数情况下,构建新的神经网络时,您将使用迁移学习。您将现有模型在流行的通用数据集(例如ImageNet或COCO)上预训练,然后将其用作特征提取器。接着在顶部添加一些新层,并用自己的数据微调这些新层。
特征提取器就是指你建立模型的其余部分在其之上的骨干,而这篇博客的目的是要找出iOS上最好的骨干——这里的“最佳”是大小,速度和预测质量的组合。
我们将使用ImageNet测试集的准确率来指示模型结构的优秀程度,但是请记住,这只是实际任务的代理。但是可以肯定的说,如果模型在ImageNet上得分更高,那么在其它任务上也可能会给出更好的结果。
注意:经常有客户和我联系,他们要求我将研究论文中的模型转换到可在Core ML上运行。我很乐意服务,但这些模型通常不适合在移动应用中使用。他们通常使用大型特征提取器,例如ResNet。转换这样的模型作为概念验证是值得的,但是一旦可行,我的建议是使用较小的特征提取器从头开始重新训练模型。
当然,您不必使用现有的特征提取器,也可以设计自己的特征提取器。但是即使如此,从现有结构中学习什么可行,什么不可行也是有意义的。
衡量就是要知道
对于每种模型结构,我将报告以下三件事:
- 训练参数的数量:它确定Core ML模型文件的大小,但也与运行时速度和预测质量有直接关系。通常,更多的参数意味着模型速度较慢,但给出的结果更好——但这并不总是成立。
- ImageNet分类准确率:我将使用原始论文中发表的值。您还可以在各种在线基准测试中找到这些分数。即使最终的任务不是分类,这也会让我们对模型的预测有多好有一定的概念。
- 推理速度:进行单个预测需要多长时间?
有时,给定模型的网站或论文会声称它使用了多少的FLOPS,这是对执行多少计算的一种度量。您可以将其用作速度的指标,但请查看我的博客文章我的模型有多快?了解为什么这经常是一种误导。
找出模型在给定设备上的真实效果的唯一方法是运行模型并测试结果。
提示:如果您只想知道模型的速度,则无需先训练模型。在Keras中转换为Core ML并在设备上进行运行尝试非常快。未经训练的模型有着与该模型的训练版本相同的计算量,因此以相同的速度运行。
给我速度!
速度很重要,因为没人喜欢等待。另外模型运行速度越快,它使用的电池电量就越少。
我从事的许多项目都涉及实时视频,通常为每秒15到60帧。在这样的app中,您希望模型更快,否则将无法实时!
我在以下设备上使用Core ML测量了推理速度:
- 装有iOS 13.3.1的iPhone 11
- 装有iOS 13.3的iPhone XS
- 装有iOS 12.4.1的iPhone X
速度测试是在CPU,GPU和神经引擎(仅适用于iPhone 11和XS)上进行的。
有趣的是,许多模型实际上在CPU上的运行速度比在GPU 上的运行速度快。惊喜! 这是因为iPhone具有强大的CPU,而且还因为调度GPU作业以及显然在Core ML本身存在开销。因此,小型模型在GPU上的运行效率不如大型模型。(另一方面,ResNet-50在CPU上的运行速度几乎慢了一倍。)
实际上,您将在可用的情况下使用神经引擎(ANE),否则将使用GPU。而不是CPU,因为通常需要它来运行app的其余部分。
速度测量如下:
let N = 100
let startTime = CACurrentMediaTime()
for _ in 0..<N {
_ = try? model.prediction(image: pixelBuffer)
}
let elapsed = CACurrentMediaTime() - startTime
print("Average time: (elapsed/Double(N))")
很简单,只是一个循环,多次进行相同的预测,然后取平均值。显然,这不是您在真实app中要做的,但是它确实使我们能够进行直接的速度测试。
注意:速度测试结果可能会有所不同。这取决于手机同时在做什么,但是这是Core ML来安排的。报告的数字也不会直接转换为每秒帧数。例如,使用MobileNet v1,以上循环每个图像花费0.0362秒,即每秒27帧。通过并行执行多个预测可达到50 FPS,您可以获得更好的吞吐量。对于某些app来说,预测一批图像而不是单个图像是有意义的,这也可以加快速度。我没有测试这样的批量预测。
ImageNet分类准确率
为了判断模型的质量,此文章着眼于ImageNet分类的准确率,即使通常这不是我们最终使用模型的目的。
ImageNet准确率通常被报告为top-1正确率和top-5正确率。前五名的分数通常更高,因为它更容易,因为该模型现在有五次机会来选择正确的答案。
您应该将这些数字视为模型真实质量的近似值,因为并非所有模型都以完全相同的方式进行训练。超参数的选择即使很小的差异也会影响结果,并且本文报告的内容可能与已发布的经过训练的模型有所不同。
此外,并非所有模型都必须以相同的方式进行评估。每个测试图像平均获取十种以上的裁剪,其结果将与单个裁剪不同。在较大的输入图像上运行的模型通常得分更高。依此类推......尽管如此,它还是使我们大致了解了这些模型的比较。
我已经提到过ResNet-50几次。这是许多计算机视觉研究人员的首选骨干。为了比较起见,常规的ResNet-50得分:
![581fd27eee0667ce5485374685fe2dbb.png](https://i-blog.csdnimg.cn/blog_migrate/c8301f692b252f0fb4c464fbd2d29dfa.png)
顺便说一下,这已不再是ImageNet上的最新分数。截至撰写本文时(2020年3月),据sotabench称,EfficientNet-L2排名第一,top-1为88.4%,top-5为98.6%。
* * *
在介绍新结构之前,让我们快速回顾一下三个长期以来的最爱:SqueezeNet,MobileNet v1和MobileNet v2。
PS:您认为Apple将特征提取器作为Core ML 4的一部分内置的可能性有多大?iOS已经配备了大型特征提取器Vision FeaturePrint Scene,但尚未针对速度进行优化。也许在iOS 14上,我们还将获得更小,更快的版本。
SqueezeNet v1.1(2016)
论文:SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size
源代码:github.com/forresti/SqueezeNet
Core ML模型:从Apple开发者网站下载
SqueezeNet是最早的表现出色的小型模型之一。它具有与AlexNet类似的ImageNet精度,后者是2012年引发深度学习革命的卷积网络,但参数却减少了50倍。
idea:使用更高效的构建块创建神经网络,以显著减少当时典型CNN使用的参数数量。AlexNet包含五个具有大内核的卷积层,然后是两个大规模的全连接层。SqueezeNet仅使用具有1×1和3×3内核的小型卷积层。
SqueezeNet的主要构建模块是Fire模块,它看起来像这样:
![23bcb182abc75f2b49c1c335fa5d01b9.png](https://i-blog.csdnimg.cn/blog_migrate/beb10dfced95371b7124713f85027de3.png)
它首先有squeeze层。这是一个1×1卷积,可减少通道数,例如,从上图中的64个减少到16个。squeeze层的目的是压缩数据,因此3×3卷积不需要学习太多参数。
接下来是具有两个并行卷积层的expand块:一个具有1×1内核,另一个具有3×3内核。这些卷积层增加了通道数,从16个增加到64个。它们的输出是级联的,因此此fire模块的输出总共有128个通道。
SqueezeNet连续拥有八个Fire模块,有时在它们之间具有最大池化层。没有完全连接层。最后是执行分类的卷积层,然后进行全局平均池化。(有趣的是,分类层都应用了ReLU和softmax。)
ImageNet分类精度:
![1c24c7c58d2aa33205d1e1a809642280.png](https://i-blog.csdnimg.cn/blog_migrate/723b50ecc63cb2c7586696a514088797.png)
这与2012年的AlexNet分数相似,但请记住,当SqueezeNet论文发表时,这不再是2016年的state-of-the-art分数。
速度测试(以秒为单位):
![1b27fd0b5069f4eda6f56a40b73de38b.png](https://i-blog.csdnimg.cn/blog_migrate/d7fbf7bb86b7cf798b630f9550dda4b4.png)
SqueezeNet之所以是最快的架构之一,仅仅是因为它的层数和学习参数相对较少。但是这种速度是有代价的:与这篇博客文章中的所有其它结构相比,SqueezeNet给出的结果更糟。如今,使用其他结构和类似数量的参数可以获得更好的结果。
我认为今天没有很多人使用SqueezeNet,但是当您使用Turi Create训练图像分类器时,SqueezeNet v1.1仍然是选择之一。
注意:可从Apple开发人员站点下载的SqueezeNet Core ML版本实际上是错误的。它的预处理层将RGB平均值(123、117、104)添加到输入图像的像素中,但是应该减去它们。
MobileNet v1(2017)
论文:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
源代码和checkpoints:TensorFlow模型
我以前写过有关MobileNet v1的文章。该结构可以追溯到2017年,这在深度学习领域已经很久了,但由于其简单性,它仍然是一个不错的选择。
idea:用更便宜的depthwise separable卷积代替昂贵的卷积层,即3×3 depthwise卷积层,然后是1×1卷积层。与常规卷积相比,这需要的学习参数要少得多,但是几乎可以完成相同的操作。
![048a44cbd54423fea0b59049be0b9d7b.png](https://i-blog.csdnimg.cn/blog_migrate/9a02153c3d2ac5e35982736ec51a37ec.png)
MobileNet v1包含13个连续的这些块。它没有使用最大池化来减小空间尺寸,但是某些depthwise层stride为2。最后是全局平均池化层,其后是一个完全连接层或一个1×1卷积用于分类。
通常,将ReLU6用作激活函数,而不是普通的旧ReLU。
注意: Core ML 3本身不支持ReLU6激活函数。相反,您必须使用四个不同的层来完成此操作:首先是常规ReLU,然后是乘-1,一个-6的阈值运算,最后是再乘-1。当我比较ReLU6与ReLU的速度时,尽管在ANE上没有显著差异,但是有常规ReLU的模型在GPU上的运行速度明显更快(推理时间约为ReLU6模型的75%)。在对MobileNet进行微调时,如果您定位的是较旧的设备,则可以用常规ReLU替换ReLU6层,以提高速度。或将其替换为一个利用MPSCNNNeuronReLUN
的自定义层。
ImageNet分类准确率:
![45d571d6cf1a43fbe2c2554592af88a5.png](https://i-blog.csdnimg.cn/blog_migrate/8617f310846ba8fd24bbd91b400d5999.png)
SqueezeNet参数的3倍以上,但得分要好得多!
速度测试(以秒为单位):
![7ab0850b6bfe2ecd46477cc724eac327.png](https://i-blog.csdnimg.cn/blog_migrate/4906db349bed5cf5581dfabf536c7c96.png)
MobileNet具有一个称为depth multipler的超参数(令人困惑的是也称为“width” multiplier),可让您选择卷积层使用了多少个通道。您可以使用它直接增加或减少学习参数的数量。在这里,我假设depth multipler为1.0。
如果使用较大的multipler,则该模型将提供更好的结果,但也会使用更多的参数,因此速度较慢。相反,较小的multipler会使模型更快,但结果较差。
例如,对于multipler 0.5,MobileNet具有1.34M参数,与SqueezeNet相似。它也以大致相同的速度运行,但具有63.3%的较高精度(top-1)。
MobileNet v2(2018)
论文:MobileNetV2: Inverted Residuals and Linear Bottlenecks
源代码和checkpoints:TensorFlow模型
Core ML模型:从Apple开发者网站下载(此模型depth multipler为1.4)
我之前也写过有关MobileNet v2的文章,所以请查看该博客文章以获取更多详细信息。
idea:像v1一样,使用depthwise卷积,但是像这样重新排列它们:
![2846c9b4f601664c5d36b6ab26f754ae.png](https://i-blog.csdnimg.cn/blog_migrate/94c53ea70cc0ec5227c9e98dbaa9e092.png)
depthwise卷积现在在中间。在depthwise层之前是1×1卷积,称为expansion层。这增加了通道数量。在depthwise层之后是另一个1×1卷积,它再次减少了通道数,称为projection层或bottleneck层。
注意:这与SqueezeNet(首先缩小,然后扩展)恰好相反。
当进入该块的通道数与输出的通道数相同(上图中的64个)时,也存在residual连接。就像在ResNet中一样,这有助于改善向后传递过程中的gradients flow。
MobileNet v2的作者称其为inverted residual,因为它在bottleneck层之间移动,而bottleneck层只有很少的通道。而来自ResNet的正常剩余连接在具有许多通道的层之间进行。
和以前一样,激活函数是ReLU6。但是,bottleneck层后面没有激活,即论文标题的线性bottleneck。由于该层产生低维数据,因此论文的作者发现,在该层之后使用非线性实际上会破坏有用的信息。
完整的MobileNet v2结构包含连续17个这种构建块。接下来是规则的1×1卷积,全局平均池化层和分类层。
ImageNet分类精度:
![78999dc8eb5c70d33e8ccb094e14ac0f.png](https://i-blog.csdnimg.cn/blog_migrate/75628e6b244f46c8fcc4a3fd237cc1e9.png)
参数比v1少得多,并且分类基准上的分数略有提高。
速度测试(以秒为单位):
![47199bc6e36a721d22299f13eef64bc5.png](https://i-blog.csdnimg.cn/blog_migrate/405394c3d773284b0763e63df2282153.png)
即使使用较少的参数,MobileNet v2的运行速度也不会比v1快很多,有时甚至会更慢。一种解释是v2有更多的层,但这似乎也是Core ML问题。当使用Metal Performance Shaders来实现,V2绝对是快了很多。
与v1一样,您可以使用depth multiplier超参数来确定模型的卷积层使用多少通道。例如,multiplier为1.4,则top-1精度提高到75.0%。如果multiplier为0.75,则top-1的准确率下降到69.8%。(表中的测试是用multiplier 1.0进行的。)
注意:在上面的MobileNet v2层的图片中,您可能已经注意到1×1卷积层有bias,而depthwise层有batch norm。那只是这个特定TensorFlow graph的产物。TF模型实际上是在conv层后面使用batch norm进行训练的。将其转换为frozen graph后,这些batch norm层被“折叠”到了卷积层中,但是由于某些原因,depthwise层并没有这样做。在推理时,Core ML无论如何应该折叠那些剩余的batch norm层。batch norm层实际上仅在训练期间才重要。
MnasNet(2018)
论文:MnasNet: Platform-Aware Neural Architecture Search for Mobile
源代码和checkpoints:TensorFlow TPU
idea:使用神经结构搜索(NAS)查找特别适合移动设备的结构。
目的是找到一种在精度和等待时间之间取得良好折衷的模型。在搜索过程中,可以通过在手机上执行潜在的新结构来直接测量它们的延迟。这称为平台感知的神经结构搜索。
测试设备上模型的速度胜于根据FLOPS的数量进行估算。但是由于这是Google的论文,所以他们主要使用Pixel手机,而不是iPhone。因此,他们的结果不一定代表iOS。
注意:还有一个不带“ m”的NASNet。该模型也是通过结构搜索找到的,但并非专门用于移动设备。
他们发现的模型如下所示:
![e53240065aec58589c6870a1e4af20c0.png](https://i-blog.csdnimg.cn/blog_migrate/e130ca220cee8c6feeeb4673ca8f3647.png)
来自MnasNet论文的插图,但上下颠倒了。
这是MnasNet-A1结构。它由许多不同的块组成,可以重复多次。其中一些使用3×3内核的卷积层,另一些使用5×5内核。这个组织看似随意的,但这就是搜索中发现的最佳模型结构。
该模型从以下几层开始:
- 具有32个filters的常规3×3卷积
- 3×3 depthwise卷积
- 具有16个filters和线性激活的1×1卷积
这些是插图中的Conv3x3和SepConv块。这与MobileNet v2的功能非常相似。
下一个块称为MBConv6。同样,这与MobileNet v2几乎相同:
- 1×1 expansion层,使通道数增加了6倍
- 3×3 depthwise卷积
- 1×1 bottleneck层可减少通道
- 来自上一个bottleneck层的residual连接(如果它具有相同数量的通道)
MnasNet中的其它块是以下的变体:
![3d56aa88359a557f8c26682af185ea83.png](https://i-blog.csdnimg.cn/blog_migrate/ac1a13c27da8e42ceb017f9692ad0656.png)
同样,它具有expansion层,depthwise卷积和末端的bottleneck层(可能还有到先前bottleneck的residual连接)。在MBConv3块中,expansion层使用系数3而不是6。有时,depthwise卷积是5×5而不是3×3。
新的东西是增加了一个squeeze-and-excitation(SE)模块。这项技术的思想来自论文Squeeze-and-excitation networks 。请注意,SE模块已明确地成为结构搜索空间的一部分——这不是搜索搜出来的。
SE的作用如下:首先,有一个全局平均池化操作(上图中的Mean层)将feature map的空间尺寸减小到1×1。如果feature map具有Dimensions H×W×C
,则现在只是带有C
元素的向量。这就是“squeeze”。
注意: SqueezeNet中的压缩还有另一个含义:在那里减少了通道数,而不是空间尺寸。
接下来是“excitation”部分:这是由两个1×1卷积层执行的,它们之间是非线性的(在这种情况下为ReLU)。第一conv层将通道数大量减少了12或24倍,第二conv层将通道数再次增加到C
。使用sigmoid将结果缩放到0到1之间。
注意:在原始的SE-Net论文中,它们使用全连接(FC)层而不是1×1卷积。由于特征图的大小仅为1×1像素,因此这两个操作在数学上是等效的。
这一切的目的是什么?这个想法是SE模块将学习哪些功能很重要。它首先压缩通道矢量,然后尝试再次还原它。结果是只有最重要的渠道才能生存。
SE分支的输出通过乘法与depthwise层的输出相乘(图中的Mul层)。这种乘法在通道尺寸上起作用,并且由于sigmoid输出在0和1之间,这仅会使激活值较小,而通道被认为不太重要。
正如原始论文所说:“ ... SE块学习如何加权传入的特征图。” 这有助于提高模型的准确性,并且由于SE层很小,因此非常便宜。
他们最终使用的最终MnasNet结构本质上与MobileNet v2相似,除了细节方面,例如卷积filter的大小(显然还有SE)。这并不是看起来那么巧合,因为他们选择结构搜索空间的方式一开始就受到MobileNet的严重影响。
同样有趣的是从MnasNet-A1开始的MobileNet v3(接下来会提到),因此显然这些模型设计相互影响。
ImageNet分类精度:
![a9c102666bc4b36c8b23db8884f44fd2.png](https://i-blog.csdnimg.cn/blog_migrate/15f33f271eccde1baa3e736fff2eb622.png)
MnasNet明显优于MobileNet v2,仅拥有12%左右的参数,因此这些架构更改是有效的。
本文还提到了MnasNet的A3变体。这实际上比ResNet-50得分高,但比A1大30%,但慢。
速度测试(以秒为单位):
![0e31135df7747ecb608de08ce74f4fd4.png](https://i-blog.csdnimg.cn/blog_migrate/3a2a2add48dc719d77e45b8e21ded97d.png)
速度测试适用于MnasNet-A1。在CPU和GPU上,MnasNet-A1比MobileNet v2略快,但在神经引擎上则不然。Core ML仅部分使用ANE来运行此模型。我怀疑这是由于SE模块使用了广播乘法。
结论:该模型比MobileNet v2更好,更快,但如果要使用神经引擎,则不是。从理论上讲,MobileNet v3应该是对MnasNet-A1的改进,但是在下一节中,您将看到我无法证实这一点。
MobileNet v3(2019)
论文:Searching for MobileNetV3
源代码和checkpoints:TensorFlow模型
v3是MobileNet的最新版本。该结构是部分通过自动网络结构搜索(NAS)找到的。
idea:使用MnasNet-A1作为起点,但使用NetAdapt进行优化,该算法会自动简化预训练的模型,直到达到给定的延迟,同时保持较高的准确率。他们还手工进行了许多改进。
本质上,MobileNet v3是对MnasNet的手工改进。
主要变化是:
- 重新设计了昂贵的层
- 使用Swish代替ReLU6
- squeeze-and-excitation模块(SE)
MobileNet v1和v2都从有32个filters的常规3×3卷积层开始。事实证明,这是一个相对较慢的层。它只有少量权重,但确实需要在比较大的224×224特征图上工作。实验表明,使用16个filters就足够了。这不会减少很多参数,但确实可以提高速度。
注意:此结果并不令我感到惊讶,因为此博客文章表明,经过预训练的MobileNet v1中的32个filters中的10个权重非常小,因此可以对其进行修剪。
在早期版本的MobileNet中,ReLU6是激活函数,而v3使用的是一种称为硬swish或h-swish的Swish版本,:
h_swish(x) = x * ReLU6(x + 3) / 6
常规的swish是x * sigmoid(x)
,但是由于Sigmoid的计算成本很高,因此将其替换为ReLU6。巧妙的技巧,但前提是您可以快速运行ReLU6......
回想一下,Core ML不直接支持ReLU6,而是需要一个四层的变通方法,而这本身是相当昂贵的。h-swish为此又增加了三层(一个加法和两个乘法)。总共有7层。
MobileNet论文来自Google,因此自然而然地他们更关注Android设备上的性能——这些设计选择是考虑到Google Pixel硬件的。MobileNet v3的作者还向TensorFlow Lite添加了优化的h-swish实现,而Core ML显然没有这种优化的算子。
剧透警报:MobileNet v3绝不慢,但使用标准Core ML层在iOS上无法充分发挥其潜力。
注意:我没有做过这个实验,但也许在iOS上,使用sigmoid进行常规swish实际上比使用ReLU6要快得多……如果您打算主要使用CPU或GPU来跑此模型,用自定义层(在Metal中是单层)来实现h-swish是可行的。请记住,自定义层当前无法在ANE上运行;但是,这可能不是一个大问题,因为反正当今的ANE硬件由于其它原因(我们很快将要讨论)还是无法处理MobileNet v3的。
并非所有模型都使用h-swish:层的前一半使用常规ReLU(第一个conv层后除外)。MobileNet的作者发现,h-swish仅在更深层上有用。并且由于特征图在早期层中往往更大,因此计算其激活成本更高,因此,他们选择在这些层上简单地使用ReLU(而非ReLU6),因为它比h-swish便宜。
如前所述,MobileNet v3使用与MnasNet-A1相同的结构。这是主要构建块的图片:
![d778beccaa69421efdb31908d4c8595f.png](https://i-blog.csdnimg.cn/blog_migrate/f705f67b8ba6ba549252185851859d97.png)
和MnasNet有一些小差异:
- 激活是h-swish(但正如前面所述,它的前面层用的是ReLU)
- expansion层使用的filters数量不同(使用NetAdapt算法找到最佳值)
- bottleneck层输出的通道数可能不同(也是由NetAdapt找到的)
- squeeze-and-excitation(SE)模块仅将通道数量减少了3或4倍
- SE模块使用公式
ReLU6(x + 3) / 6
作为粗略近似值,而不是sigmoid(就像h-swish所做的一样)
注意:如果您想知道ReLU6(x + 3) / 6
发生在哪里,那么右分支中的Mul层将乘以0.16667,即除以6。ReLU6被融合到卷积层中。但是x + 3
部分在哪里?TFLite转换器很聪明,实际上在卷积层的bias上加了3,这是一个聪明的微优化,节省了在单独的层中进行加法的过程。我们也可以在Core ML模型中进行此优化节省一层。
最终的优化涉及最后的层。
在MobileNet v2中,在全局平均池化层之前,是一个1×1卷积,可将通道数从320扩展到1280,这样我们就有很多特征可以被分类器层(或其它任何搭在这个骨干上的层)利用。但是,与模型的其余部分相比,像这样的大卷积层也相对较慢。
在MobileNet v3中,该层位于全局平均池化层的后面,它可用于更小的特征图(1×1而不是7×7),因此速度更快。这个小小的变化也使我们可以删除以前的bottleneck层和depthwise filtering层。他们总共能够去除三层昂贵的层,而不会降低准确率。
这是模型输出阶段的图示:
![20c07fbae066ea8de8d682089bbf24fe.png](https://i-blog.csdnimg.cn/blog_migrate/5a5c3ca895f6d5769500f3821ea29aed.jpeg)
(请注意,在这些最后的卷积层后面,现在没有了batch normalization。)
由于这些额外的改进,即使MobileNet v3使用相同类型的构造块并且比MobileNet有更多参数,MobileNet v3仍比MnasNet更快,并且具有相同的精度!
至少在Pixel手机上……我看不到iPhone上的这些速度提升。我的猜测是,这主要归因于所有那些ReLU6层,但我尚未进行详细研究。
顺便说一下,MobileNet v3有多种变体:
- Large:我上面描述的
- Small:构建块较少,filter数量较少
- Large minimalistic:类似于“large”,但没有SE,h-swish,5×5卷积
- Small minimalistic:类似Small
MobileNet v3仍然使用depth multiplier的概念。因此,有很多方法可以调整此模型的大小和形状。像以前的迭代一样,该结构不仅定义了单个模型,而且定义了整个模型家族。
提示:论文Searching for MobileNetV3 不只是图像分类。它还描述了如何将其用于目标检测(作为SSDLite中骨干的直接替代),并提出了语义分割的新扩展(LR-ASPP或Lite Reduced Atrous Spatial Pyramid Pooling)。如果您感兴趣值得一看。
ImageNet分类精度:
![b7114d25234856c7b13d4a7040118f64.png](https://i-blog.csdnimg.cn/blog_migrate/e06badb1e50139b0651a8e632007f9e2.png)
Large版的精度几乎与ResNet-50相同。它比具有相当数量的参数的MnasNet-A3低点。
它绝对比带1.0 depth multiplier的MobileNet v2更好,参数也更少(3.47M)。我要说的是,将它与具有1.4 depth multiplier(6M参数)的v2进行比较更公平,它也有75%的top-1精度。
Small版可以与depth multiplier 0.75(具有2.6M参数)的v2进行比较。有趣的是,v2在那儿得分更高(69.8%的top-1)。
速度测试(以秒为单位):
![f633bd455e9df4d59e6bc024d79bf3bd.png](https://i-blog.csdnimg.cn/blog_migrate/283aac80c9f4e5b8310a9f5feef4f5b5.jpeg)
以上测量是针对depth multiplier 1.0的。您也可以下载用0.75 multiplier 的checkpoints,但我没有对此进行测试。
结论:large v3模型的准确率优于v2,并且在CPU和GPU上更快。但是,在神经引擎上它要慢得多 ——调试表明Core ML在GPU上运行了该模型的某些部分。
注意:为什么ANE运行此模型有问题?我不确定,但我想这与squeeze-and-excitation块有关。在这种块的末尾,我们对1×1×C
张量与H×W×C
张量进行了广播乘法,我怀疑神经引擎上尚未支持此操作。
尽管对架构进行了额外的手动调整,但MobileNet v3的运行速度并不比iPhone上的MnasNet-A1快。我相信,这主要是Core ML在ReLU6之类的东西中引入的开销。不幸的是,这抵消了其它速度改进。这可能可以使用自定义层来解决此问题。
我不确定目前是否建议将此结构与Core ML配合使用:准确率更好,最好的情况下速度大致相同,最坏的情况下速度较慢,并且模型占用app bundle的空间比原来多1.5倍。
您必须自己决定为了更好的结果是否值得额外的付出,还是坚持使用更简单的结构(例如MobileNet v2)更好。
BlazeFace (2019)
论文:BlazeFace: Sub-millisecond Neural Face Detection on Mobile GPUs
源代码和checkpoints:MediaPipe
BlazeFace是Google专门为移动GPU设计的人脸检测模型。您可以将其作为MediaPipe的一部分使用,MediaPipe是一个用于构建计算机视觉管道的C ++框架。(我最近也将BlazeFace移植到了PyTorch。)
即使不打算将其用作通用计算机视觉模型,但由于其轻量的特征提取器,我在本文中也包括了BlazeFace 。根据本文所述,此特征提取器是专为目标检测而设计的,但这并不意味着我们不能将其重新用于其它任务。
有趣的是,即使是Google的这篇论文,也特别提到了iPhone和Metal Performance Shaders(不是神经引擎)。
此结构的主要构建块称为BlazeBlock:
![d9d581a98958f5944a18551eb7ec7800.png](https://i-blog.csdnimg.cn/blog_migrate/a77dbfb79b6543d8d743536fc8d0bda2.png)
就像MobileNet v1中一样,在左分支中是一个depthwise separable卷积。右分支是residual连接。
与MobileNet相比,他们进行了以下更改:
- 将depthwise卷积的核大小增加到5×5。这样做的理由是,与1×1卷积相比,depthwis卷积相对便宜,因此您也可以使其变大。这也是MnasNet中发生的事情,尽管MnasNet并非到处都在做。
- residual连接实际上是在depthwise层之间,而不是在bottleneck层之间(如在MobileNet v2中所做的那样)。
- 始终存在residual 连接。如果通道数由于1×1卷积而改变,那么将添加一个通道填充层,该层将空的特征图简单地附加到张量的背面。
- 一些depthwise层的步幅为2。发生这种情况时,residual分支还包括最大池化。
- 激活函数是常规ReLU(不是ReLU6)。
BlazeFace特征提取器有连续16个这些的构建块。这是一个非常简单的结构,这就是为什么它很快的原因。
BlazeFace的输入图像大小为128×128,小于本文中讨论的其它模型(通常为224×224或227×227)。输出特征为8×8×96,也比通常的小。
注意:论文中还提到了一个“双” BlazeBlock,它在左分支中有两组卷积。但是,MediaPipe中的预训练模型只有单个BlazeBlocks。
ImageNet分类精度:
![daad971a1a02436679733dfe797e0820.png](https://i-blog.csdnimg.cn/blog_migrate/b895b6c0b0d3b903efd03b89815272e7.png)
论文中没有提及特征提取器的ImageNet准确率分数。但是,它的确会看人脸检测数据集的平均精度(AP)。在该任务上,完整的BlazeFace人脸检测模型得分高于MobileNetV2-SSD。
当然,这并不能证明BlazeFace的特征提取器要优于MobileNet的特征提取器,但是我预期它不会比类似数量参数(BlazeFace只有10万!)的模型更糟!
但是,我们不要着急:论文没有解释他们使用的MobileNet v2模型的配置,并且论文中描述的BlazeFace模型与可下载模型并不完全相同。
因此,除非有人在ImageNet上对BlazeFace进行重新训练,否则我们不知道它的真正表现。
注意:如果要在自己的模型中使用此特征提取器,则可能需要在ImageNet上训练一些epochs,因为它目前仅在人脸上进行了训练。
速度测试(以秒为单位):
![0ffa0c9f4d3b1c5b0cfe5a4e3f327d4a.png](https://i-blog.csdnimg.cn/blog_migrate/7aa8ec47a4654057a45dc7ca1929e702.png)
PyTorch→ONNX→Core ML转换在通道填充层上产生了错误,因此我无法制作Core ML模型来进行速度测量。由于BlazeFace特征提取器仅有100k参数,并且可以处理较小的128×128图像,因此我敢打赌它会很快……
注意:应该可以使用Core ML 3中引入的ConstantPaddingLayer
进行通道填充,但是我认为ONNX转换器会将填充量置于错误的顺序。我不想修复它,因为我们都没有ImageNet的准确率得分。
结论: BlazeFace的特征提取器可能值得在模型设计中进行试验。它体积小且速度快,但是与其它YOLO9000: Better, Faster, Stronger,YOLOv3: An Incremental Improvement模型相比,我没有任何数据可以证明其实际性能如何。
TinyYOLO / Darknet(2016-2018)
纸张:YOLO9000: Better, Faster, Stronger,YOLOv3: An Incremental Improvement
源代码和checkpoints:pjreddie.com/darknet/yolo/
Core ML模型:从Apple开发者网站下载
在博客上,我已经写过几次有关YOLO的文章。YOLO是一种快速的one-stage目标检测器。它还具有较小的版本TinyYOLO更适合在移动设备上使用。
就像BlazeFace一样,由于其特征提取器(也称为Darknet),我将TinyYOLO包括在此博客文章中。
为什么我要关心TinyYOLO特征提取器?CPU或GPU上的TinyYOLO绝对比其它流行的检测模型MobileNet v2 + SSDLite慢很多。但是在神经引擎上,它实际上似乎更快……这是怎么回事?
我的假设是TinyYOLO仅有卷积层和池化层的相当“老式”的结构正是ANE所喜欢的。使用诸如depthwise separable卷积等巧妙技巧的MobileNet等模型在GPU上运行得很好,但可能无法最佳利用ANE。
这是真的吗?我们拭目以待…
补充工具栏:不幸的是,Apple没有提供任何有关神经引擎如何工作以及如何利用它的信息。拥有一个文档,该文档中应避免使用哪些层类型,如何设计模型以最大程度地利用ANE,这将很有帮助。这将消除猜测的必要。
TinyYOLO v2是一个非常简单的卷积网络,由八个3×3卷积和最大池化层组成,其中三个卷积之间有最大池化层,用于进行边界框预测。特征提取给出了一个很大的(13, 13, 1024)
张量。
自从我上一次写有关YOLO的文章以来,第3版已经发布。v3中的第一层与以前相同:
Layer kernel filters
-------------------------------
Convolution 3×3 16
MaxPooling 2×2
Convolution 3×3 32
MaxPooling 2×2
Convolution 3×3 64
MaxPooling 2×2
Convolution 3×3 128
MaxPooling 2×2
Convolution 3×3 256
所有卷积层都紧接着 batch norm 和0.1斜率的Leaky ReLU。
此时,模型分为两个分支。第一个分支如下所示:
Layer kernel filters
-------------------------------
MaxPooling 2×2
Convolution 3×3 512
MaxPooling 2×2
Convolution 3×3 1024
Convolution 1×1 256
-------------------------------
其输出进入另一个具有128个filters的1×1卷积,然后以2的系数上采样并与第二个分支连接。接下来是进行边界框预测的另一组卷积,但我们对此不感兴趣。
就像v2一样,它仍然主要是卷积,之后是最大池化。没有什么花哨。
注意:我不完全确定特征提取器在哪里结束以及目标检测器在哪里开始。您可能不会保留第二个分支,因为第二个分支主要用于帮助检测更高分辨率的特征图中的目标。
YOLO的论文实际上并未解释模型的这些微小变化。取而代之的是,他们描述了特征提取器的完整版本Darknet-19和Darknet-53,它们更加复杂,并且还使用了残差连接之类的功能。
ImageNet分类精度:
![3bd9d4bf21117d103328e9ec7d0dcc3f.png](https://i-blog.csdnimg.cn/blog_migrate/2af33710208ddddead0d8289d3ab4fef.png)
该论文没有给出tiny版的ImageNet分数,但是Darknet-19的top-1分数是74.1%,Darknet-53的分数是77.2%。TinyYOLO的分数可能会差很多。
请注意,v2最有1024个输入和输出通道,因此卷积很大,这就是为什么v2的参数几乎翻倍的原因。
速度测试(以秒为单位):
![a00362ba3bf148fef5f9e6ef22b5d360.png](https://i-blog.csdnimg.cn/blog_migrate/ec38ebfbb633c10b748ebd34d1845f91.jpeg)
这些测试是在去除边界框预测层的情况下完成的。
与YOLO一起使用的输入图像是416×416,比此处讨论的大多数其它模型大。但是,我对256×256图像进行了速度测试,以使比较更公平(这也是特征提取器最初使用的训练方法)。在416×416的图像上,模型的速度大约是表中所示速度的两倍。
结论:好吧,我想我的假设是…… 不正确的!
仅看特征提取器时,MobileNet v2在GPU上肯定更快——但在ANE上也更快!
那么,为什么TinyYOLO对象检测器比ANE上的MobileNetV2 + SSDLite运行得更快?一定是因为有SSD层。没有这些层,MobileNet肯定会击败YOLO。
注意:公平的说,当我将TinyYOLO与MobileNet + SSD进行比较时,SSD边界框解码逻辑是Core ML模型的一部分。但是使用TinyYOLO时,解码是通过Accelerate框架在CPU上完成的。我不知道这种差异对速度有多大影响,但可能会很大。也许我会在以后的博客文章中比较目标检测模型的性能,因此可以对其进行更详细的介绍。
如果您要构建需要在神经引擎上运行的实时目标检测器,则TinyYOLO可能是更好的选择(不要相信我:您自己测试)。但是,作为特征提取器,我仍然更喜欢MobileNet。
由于我们也没有TinyYOLO的特征提取器的ImageNet准确率数据,因此我不认为我可以做出推荐。
注意:完整的YOLO v3怎么样?就个人而言,我不会在手机上使用它。这是一个很大的模型。它提供比MobileNet + SSD更准确的结果,但速度也慢得多。为了提高速度,您绝对需要tiny版。
SqueezeNext(2018)
论文:SqueezeNext: Hardware-Aware Neural Network Design
源代码和checkpoints:github.com/amirgholami/SqueezeNext
顾名思义,SqueezeNext基于SqueezeNet,但在结构方面进行了许多改进。
新的SqueezeNext块如下所示:
![f94a20abd06beff5269c9859061406a6.png](https://i-blog.csdnimg.cn/blog_migrate/131a79045502ed8d28d2d45a8d1523fb.png)
每个块中有五个卷积层,全部都有batchnorm和ReLU:
- 前两层是bottleneck层,即1×1卷积,可减少通道数。如果
C
是输入通道数,则第一bottleneck层将其减少为C/2
,第二bottleneck层将其减少为C/4
。
与原始的SqueezeNet一样,这些bottleneck用于减少进行实际过滤的卷积层所需的参数数量。为什么要连续使用两个bottleneck层?不知道,但也许这比单一的步骤从C直接降到C/4有更好的结果。层越多越好! - 与原始的SqueezeNet不同,不再有3×3卷积。相反,它被分为两个较小的卷积:3×1和1×3。它们都有
C/2
filters。将其分为两个较小的层可减少所需参数的数量。同时,它增加了网络的深度,通常可以改善模型。(甚至更多层!)
这两个卷积的顺序交替出现。如果此块具有3×1,然后是1×3,则下一个块首先进行1×3,然后进行3×1,依此类推。我想他们这样做是为了使事情变得有趣。 - 第五层也是最后一层是expansion层,即1×1卷积,将通道数带回
C
。
与现代结构一样,也存在residual连接。
回想一下,原始的SqueezeNet在两个分支中都有卷积,但是这里没有发生:residual分支中没有卷积。但是,此规则有一个小例外...
SqueezeNext中的块分为四个部分。在每个新部分中,特征图的空间尺寸均减半。为此,第一个bottleneck卷积stride为2。现在,该块的residual分支还必须有stride 2卷积,否则两个分支的输出不能求和。
(此外,在第一个块中,输出通道的数量可以与输入通道的数量不同,因此有residual连接的分支也必须与之匹配。)
注意:奇怪的是,官方的Caffe模型在与主分支的residual连接求和之前和之后都应用ReLU。我以前从未在其他类似ResNet的模型中看到过——似乎ReLU太多了。与此相对应的是MobileNet v2,该版本这里完全没有激活。
SqueezeNext中的第一层是7×7卷积,具有64个filters和stride 2。此层不使用零填充。紧随其后是最大池化,因此227×227像素的输入大小很快就减小到55×55像素。
(不重要的细节:由于池化层的原因,第一节中的第一个卷积的stride为1而不是2。不确定为什么要在此处而不是其它任何地方使用最大池化层。)
模型的末尾是执行实际分类的单个全连接层。就在该层之前是bottleneck层,它减少了通道数,从而在FC层中节省了许多参数,并设有全局平均池化以减小空间尺寸。(SqueezeNet实际上使用卷积层进行分类,最后进行全局池化。)
与MobileNet一样,SqueezeNext不仅是单一的固定设计,还是一系列可能的结构:
- 一个宽度乘数确定的在每个块中的filters的数量。论文研究了1.0、1.5和2.0的宽度乘数。
- 您还可以更改所使用的构建基块的数量。论文显示了具有23、34和44个块的模型。如您所料,更多的块会带来更好的结果。
- 您可以更改每个部分中有多少个块。例如,“ v5”变种在前两个部分中具有相对较少的块(在尺寸为55×55和28×28的特征图上起作用),在第三部分中有很多块(特征图尺寸为14×14),以及最后一节中只有一个块(大小7×7)。
- 在SqueezeNext的其他变种中,第一个bottleneck以及1×3和3×1层使用组大小为2的组卷积,这将这些层的参数数量减少了一半。(这有点像使它们成为depthwise卷积,这是一种分组卷积,其中组数等于通道数。)
SqueezeNext的作者没有特意使用depthwise separable卷积,因为它们“由于算术强度低(计算与带宽之比)而在某些嵌入式系统上无法提供良好的性能”。
有趣的是,由于depthwise separable卷积实际上在iPhone GPU上能很好地工作(请参阅MobileNet的成功经验)。本文没有详细介绍他们打算将SqueezeNext用于哪种嵌入式系统。
为了尝试不同的设计方法,作者在假设的神经网络加速器芯片上模拟了可能的结构的性能。这与MnasNet有所不同,后者在实际硬件上尝试了结构。因此,我不确定SqueezeNext的设计决策能否很好地转化到现实世界——至少iPhone硬件上。
本文还显示了使用Iterative Deep Aggregation (IDA)模型的结果。不同于在最后进行分类的线性块序列,对于IDA,我们已经在每个块之后进行了预测,然后将这些预测与最终分类层的预测相结合。这个idea提高了准确率(一点),但是以更多的参数为代价。(这似乎不是SqueezeNext的主要功能。)
ImageNet分类精度:
![e287241a73a8c58b7a814634fc934fad.png](https://i-blog.csdnimg.cn/blog_migrate/32a6da2c54d6ebc4005b252dc031079b.jpeg)
这些是结构几个不同变种准确率得分。
可以将1.0-SqNxt-44模型与旧的SqueezeNet进行比较。尽管它的得分比原始得分更高,但是即使我们将其与参数数量相似(0.5深度乘数,top-1得分为63.3%)的MobileNet版本进行比较,其准确率仍低于MobileNet v1。
SqueezeNext论文声称与MobileNet v1相比,top-5的准确性更高,参数减少了1.3倍。为了获得此结果,他们将其2.0-SqNext23v5模型与MobileNet-1.0-224进行了比较。但是……他们正在使用的MobileNet版本不如官方版本好——他们使用与自己的模型相同的超参数对其进行了训练,以获得更公平的比较。
我认为这是有道理的,但它也使“比MobileNet更好”的说法有点可疑(尤其是因为SqueezeNext的top-1准确率实际上并没有更好)。
速度测试(以秒为单位):
![befbb508f2036e5cc0ac6b37ad878c28.png](https://i-blog.csdnimg.cn/blog_migrate/5e7c5d4727b1029e10b8a4769e461658.png)
测试是针对最大的模型2.0-SqNxt-23v5进行的。该模型的准确率与MobileNet v3(较小)相似,但速度却差得多。(在ANE上除外,MobileNet v3的表现不佳。)
结论:似乎大多数这些较新的体系结构在bottleneck层,expansion层和residual连接方面都做类似的事情——SqueezeNext也不例外。我喜欢将3×3卷积分为3×1和1×3的idea,但是我不确定实际上是否比depthwise separable卷积更好。
SqueezeNext非常适合参数相对较少的模型,但是在iPhone上,我仍然会选择MobileNet。
ShuffleNet(2017、2018)
论文(v1):ShuffleNet: An Extremely Efficient Convolutional Neural Network for Mobile Devices
论文(v2):ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design
源代码和checkpoints:github.com/megvii-model/ShuffleNet-Series
ShuffleNet早在几年前就已经存在了,并且已经存在于我的to-do list中很久了,因此我正在用此博客文章来最终了解它。 有几个不同的版本,所以让我们从v1开始。
idea:许多现代结构都使用许多密集的1×1卷积,也称为pointwise卷积,但是它们可能相对昂贵。为了降低成本,我们可以在这些层上使用组卷积。但是这些都有副作用,可以使用channel shuffle操作来缓解。
逐组卷积将输入特征图在通道维度上划分为两个或更多组,并对每个组分别执行卷积。就像将输入切成多个较小深度的特征图,然后对每个特征图进行不同的卷积一样。
对于两组,您只需要一半的参数,因为每个卷积filters现在都可在一半的输入通道上工作,并产生一半的输出通道。(权重在组之间不共享——每个组仍在学习自己的参数!)
注意:组卷积类似于depthwise卷积。实际上,有时使用更通用的分组卷积来实现depthwise卷积。区别在于,使用depthwise卷积时,每个输入通道是其自己的组,并且每个输入通道都有一个输出通道。组卷积是更genearal的形式,每个组的输出通道数不必等于组中的输入通道数。
分组卷积的副作用是每个输出仅从一部分输入中得出,即,输出通道也分为相同数量的组。这是不理想的,因为不同组之间没有信息流,这限制了网络学习有趣事物的能力。
解决方案很简单:之后再shuffle一下。
分组卷积后,通道shuffle操作将沿通道维重新排列输出特征图,如下所示:
![6a6807d6ba937f98ff419a1961dfd00c.png](https://i-blog.csdnimg.cn/blog_migrate/567d40cec5b06f643fffc4c0e9bb25b3.png)
这可能看起来很复杂,但是可以使用基本的reshape和transpose操作轻松实现。如果G
是组数,并且K
是每个组的通道数,则:
- reshape输入张量
(N, C, H, W)
为(N, K, G, H, W)
- transpose数组中的
G
和K
维度,所以现在张量具有形状(N, G, K, H, W)
- reshape张量回
(N, C, H, W)
ShuffleNet v1中的构建块如下:
![ccd33d80338b47fa5f28836ac7f23ea2.png](https://i-blog.csdnimg.cn/blog_migrate/d9a4160fd083e0c579dfd8234929f5eb.png)
- 第一个卷积是一个1×1 bottleneck层,将通道数减少了4倍。该层使用分组卷积,然后进行通道shuffle。
- 3×3层是有batchnorm但没有ReLU 的depthwise卷积。不使用ReLU可以得到更好的结果。
- 最后一层是另一个1×1 分组卷积,用于再次扩展通道数(以匹配residual连接的通道数)。在这一层上,没有通道shuffle,因为作者发现它在那个地方没有任何区别。
- 像通常一样,存在residual连接。
- 有时depthwise层的stride为2。在这种情况下,左分支内部有一个3×3的均值池化层,结果与主分支concatenate而不是add在一起。
论文讨论了不同group size的实验,但总体上group 为8似乎给出了最佳结果。组越多,模型所需的参数越少,其计算复杂度就越小。或换个角度来看,对于相同量级的复杂性,您现在可以拥有更多的特征图并获得更好的准确率。
完整的结构从stride为2的常规3×3卷积开始,然后是最大池化。然后是三个阶段,每个阶段有4或8个ShuffleNet块。该阶段的第一个块stride为2。最后,是全局平均池化和进行分类的全连接层。
好的,这就是v1的结构。这篇论文对这些基于组的卷积做出了很大的贡献,但是不久之后,作者改变了主意 ……
让我们看看version 2发生了什么并学习之。
ShuffleNetV2论文有关于不同类型的层在实际硬件上性能如何的一个有趣的讨论。作者利用这些见解提出了一种改进的网络结构。
在分析模型的速度时,他们意识到进行分组卷积不值得。它们确实有需要较少的参数和计算的好处——但是,如果您随后用它来证明拥有更多的通道以提高模型的准确率,则存储器访问的数量也会增加。当涉及到速度时,正是这些额外的读写操作使模型变慢了。
新的ShuffleNet v2构建块如下所示:
![2b4d4ac331c758f18a3946514a406dba.png](https://i-blog.csdnimg.cn/blog_migrate/6b10cfe7401ae22acd552eac4550d31d.png)
这是更改的内容:
- 为了替换组卷积,有一个新的通道拆分操作,该操作通过左分支发送一半通道,而通过右分支发送另一半通道,就像使用两个组一样。
- 1×1卷积不再成组。
- 卷积现在始终具有相同数量的输入和输出通道。他们发现,当通道数保持不变时,卷积中的内存访问量是最佳的。
- 现在,shortcut连接始终是concatenate,而不是求和——这是开始时通道拆分的反向操作。(因此,从技术上讲,它不再是residual连接。)
- 该通道shuffle仍然存在,但已经转移到了尽头。
他们使用concat,而不是相加两个分支的主要原因是按元素运算,如加法是相对昂贵的——他们进行了大量的内存访问,但很少做计算。由于可以将concat,通道 shuffle和通道拆分合并为单个元素操作,因此可以对其进行优化。
注意:depthwise卷积stride为2时,左分支略有不同。这将获得自己的3×3 depthwise的卷积,stride为2,然后是1×1的卷积,以确保两个分支的输出具有相同的空间尺寸(或者不能concatenate)。在这样的块中没有通道拆分操作,因此两个分支都对相同的数据起作用,并且concat有效地使通道数加倍。
除了对构建块进行更改之外,该模型的总体结构与v1中的相同,不同之处在于,在全局平均池化和最后的全连接层之前现在有一个1×1的大卷积层。
还有一个较新的变种ShuffleNet v2 +,与MobileNet v3中一样,它增加了hard-swish,hard-sigmoid以及squeeze-and-excite。
ImageNet分类精度:
![2dc8cd608791b3bb52ffed141dd83be0.png](https://i-blog.csdnimg.cn/blog_migrate/9ec1be601bb93479fc982e3d055a7c93.jpeg)
ShuffleNet v1 可以与Mobilenet v1(0.75 depth multiplier)相提并论。
1.0 scale factor的ShuffleNet v2比ShuffleNet v1更好。(scale factor就像其它模型中使用的depth multiplier一样。它增加或减少了整个网络中卷积层使用的filters的数量。)
具有1.5 scale factor的ShuffleNet v2与MobileNet v2相当,甚至更好。
在参数数量大致相同的情况下,ShuffleNet v2 +(medium)比MobileNet v3(large)要好一点。
到目前为止,ShuffleNet v2 +(large)是本博文中得分最佳的模型,但它也是最大的模型。
速度测试(以秒为单位):
![361387f7065332e393266eedc9667978.png](https://i-blog.csdnimg.cn/blog_migrate/6993b31fb78c73a2c0ee6595be99645c.png)
测试适用于ShuffleNet v2 1.5×。我没有iPhone X的测试结果,因为我的系统运行iOS 12,并且该模型需要iOS 13或更高版本,这是因为通道shuffle层的转换方式(理论上应该可以制作iOS 12版本)。
结论:准确率得分是迄今为止我们在此博客文章中看到的最好的分数。在相同数量的参数下,它们通常比MobileNet更好。
但是……这个模型根本不能在GPU上很好地运行!我认为这是由于通道shuffle转换为Core ML的方式的原因。它最终是reshape/transpose/slice/squeeze层的组合,可以由单个Metal内核(或至少由更有效的Core ML层选择)代替。
CondenseNet(2017)
论文:CondenseNet: An Efficient DenseNet using Learned Group Convolutions
源代码和checkpoints:github.com/ShichenLiu/CondenseNet
idea:与ShuffleNet v1一样,对1×1层使用组卷积,但要学习分组。
起点是类似于DenseNet的结构,在该结构中,每个层的输出都与之前的所有层的输出连接在一起。以这种方式重用特征有助于提高准确率。
但是,这种密集的连接可能超出了我们的需求,因为较后的层可能不一定总是需要较早层的特征。当然,问题是您事先不知道应该重用哪些特征。
这就是CondenseNet的用武之地:在训练期间,它学习来自较早层的哪些特征足够重要。
它通过将卷积层中的filters分为几组来完成此操作,通常每层4或8组。
随着时间的流逝,认为不那么重要的输入特征将从模型中删除。这是按组完成的,因此给定的输入特征可以从一组filters中删除,但仍可被另一组使用。
训练完成后,该层中的每个组仅保留1/C
原始filters,C
即所谓的condensation factor。C
通常是4或8。
在推理时,我们不必担心这些。但是,我们确实需要忽略来自已修剪掉的较早层的特征图。我们还需要重新排列其余的输入通道,以将它们分配给正确的组。这是通过索引层完成的,它只是一个查询表。
![a3aa7d45e5e5dff54a3db20c4b0bffdc.png](https://i-blog.csdnimg.cn/blog_migrate/94cbc03d8228faafd4403d891133c177.png)
然后可以通过普通的组卷积来进行实际的卷积,这比使用稀疏卷积要有效得多。
跟在ShuffleNet中一样,此后是一个通道shuffle 操作,以改善组之间的信息流。
ImageNet分类精度:
![32298e476ed58a3d4f1923534f1bf51f.png](https://i-blog.csdnimg.cn/blog_migrate/c5dfa274f09aed322c86ced163258ce9.png)
这些分数还不错,可以与MobileNet和ShuffleNet v1&v2相提并论。
速度测试(以秒为单位):
![68c880ae4a6ad491fb5dba4fcb8c6a3c.png](https://i-blog.csdnimg.cn/blog_migrate/19f38f32553ec01042f3b3f9ea154383.png)
测试是针对较大模型的。看来CondenseNet在iPhone上有一些问题,特别是在GPU上速度非常慢的情况下。
(由于我的iPhone运行iOS 12,因此我没有iPhone X的结果。该模型需要iOS 13或更高版本,因为“索引层”是通过Gather操作生成的。)
结论:有趣的想法,尤其是因为类似DenseNet的结构通常不在移动设备上使用。但是,如ShuffleNet v2所示,分组卷积并不是真正的答案……
该论文声称,CondenseNet只有一半计算量就达到了与MobileNet相似的准确率,但计算并不是全部。如速度测试所示,此模型在Core ML上有点慢。
ESPNet(2018)
论文(v1):ESPNet: Efficient Spatial Pyramid of Dilated Convolutions for Semantic Segmentation
论文(v2):ESPNetv2: A Light-weight, Power Efficient, and General Purpose Convolutional Neural Network
源代码和checkpoints:github.com/sacmehta/EdgeNets
Core ML模型:iOS demo app
我对ESPNet v2最感兴趣,但让我们首先来看一下v1。
idea:将标准卷积层分解为pointwise卷积,然后是空洞卷积的空间金字塔。
将卷积拆分为1×1层再加上“其它内容”是很常见的,但是这里的其它内容与我们到目前为止所看到的有所不同。
Efficient Spatial Pyramid(ESP)模块如下所示:
![02023eb774044dbe4b226fe1f012cf97.png](https://i-blog.csdnimg.cn/blog_migrate/573be9c0ed64ee041ab09b78f24f9750.png)
像往常一样,1×1卷积(图片中的Conv-1)是减少通道数量的bottleneck层。有一个“width divider”超参数K
,它确定程度。如果N
是原始数量的输出通道,则bottleneck层有N/K
输出通道。
空间金字塔由几个平行的3×3卷积层(DConv-3)组成。这些是空洞卷积,扩张率为1、2、4、8、16,依此类推。使卷积膨胀可以扩大从中学习的感受野。有K
个这种膨胀内核,每个内核都有N/K
filters。
之后,空间金字塔的输出将沿着通道维度进行concatenate,因此输出通道的最终数量将又是N
。
注意: “ Add”层执行分层特征融合(HFF)。这样做是为了消除由于空洞卷积中的间隙而出现的artifacts,例如棋盘格图案。
当然,还有不可避免的residual连接以帮助梯度流动。
看起来ESP模块比标准卷积做多得多的工作,但实际上它具有较少的参数(由于pointwise层),并且具有更大的感受野(由于空洞卷积)。
ESPNet v1专为语义分割而设计。ESPNet v2建立在v1的思想基础上,旨在用于通用计算机视觉任务,甚至是语言建模之类。
idea:使空洞卷积depthwise separable。
新的构建块名为EESP,它代表极高效的空间金字塔(Extremely Efficient Spatial Pyramid),如下所示:
![b82768922c28534b7c4a27fabfd8f0d9.png](https://i-blog.csdnimg.cn/blog_migrate/4de94b18e36c2b3f9773e6c15e6a3868.png)
就像在ShuffleNet中一样,它对1×1 bottleneck层(图片中的第一个GConv-1)使用组卷积,尽管它不进行通道shuffle。
现在,空洞卷积分为两部分:首先是也已扩张的3×3 depthwise 层(DDConv-3),然后是1×1的pointwise层。
他们没有计算K
个单独的1×1层,而是将扩张层的结果连接起来,然后对其应用单个1×1 分组卷积(底部的GConv-1)。这是等效的,但效率更高。
激活函数是PReLU。
完整的结构从具有stride 2的常规卷积层开始。接下来是三个阶段。每个阶段均以strided EESP块开始,以将空间尺寸减半并将通道数量加倍。该阶段的其余部分由几个常规EESP块组成。在这三个阶段之后,还有更多的卷积层,全局平均池化和全连接的分类器层。
Strided EESP在空洞卷积上的stride为2。residual连接被平均池化和concatenation代替,这将使通道数增加一倍。(这比将卷积层中的filters数量加倍要快。)
此外,它们还添加了另一个远程shortcut连接,该连接一直返回到输入图像。这种新的连接具有一个或多个平均池化层,然后是depthwise separable卷积。这个idea是,这种远程连接会引入一些额外的空间信息,否则这些信息可能会因下采样而丢失。
ImageNet分类精度:
![fa0a5168191db557d458de66e2255078.png](https://i-blog.csdnimg.cn/blog_migrate/2c157fba70d1672652df08d1562484f4.png)
这与MobileNet v2和ShuffleNet v2的得分相似。该论文提到ESPNet v2的FLOPS数量较少,但众所周知,FLOPS并不能说明速度方面的全部情况。
注意:与这些现代模型类型一样,ESPNet也使用宽度缩放因子。我不确定5.9M参数模型使用什么比例因子。该文件没有提到这一点。也没有针对此尺寸的预训练模型。
速度测试(以秒为单位):
![f5130dbce82c8e692fa31972010b1a0e.png](https://i-blog.csdnimg.cn/blog_migrate/712f64088f42c92d3a3bb9ab2d20803a.png)
针对2.0x 比例因子的ESPNet v2进行测试。
注意:我无法在ANE上获得结果,Core ML因“程序推理溢出”错误而失败。我曾在未经训练的模型(具有随机权重)上看到过几次,但实际上这个是经过训练的。奇怪。
结论:这相当慢。我认为一个问题是,将卷积分成很多较小的层并不一定是有益的。执行许多小操作的开销可能会抵消任何潜在的速度提升。
这种模型的额外复杂性抵消不了在准确率上稍为提高。仅通过计算FLOPS的数量,模型在理论上可能会“更快”,但在实践中它会变慢,因为模型结构对硬件不友好。
DiCENet(2019)
论文:DiCENet: Dimension-wise Convolutions for Efficient Networks
源代码和checkpoints:github.com/sacmehta/EdgeNets
这和ESPNet来自同一个人。顺便说一下,其中一些作者隶属的公司Xnor.ai 最近被Apple以 的的价格收购了。谁知道我们是否会在某个时候在iOS中看到某些这项技术。
idea:用按维度的卷积和融合代替常规的卷积。
怎么说呢?本博客文章中讨论的大多数神经网络都是围绕一些聪明的新想法构建的,以将普通的旧卷积分解为更小,更有效的运算。这也不例外——我们只需要弄清楚“按维度进行”的含义。
如您所知,通过深度(depthwise)卷积和组卷积,我们沿通道维度对输入张量进行了切片,并且每个卷积filters都在其自己的通道子集上运行。但是为什么不沿宽度或高度尺寸切片呢?
深度卷积的缺点在于,它需要接着1×1层以混合通道。正如DiCENet论文所指出的,在MobileNet等模型中,这些pointwise卷积占了所有运算的90%。ShuffleNet尝试通过使用分组卷积使1×1卷积更快来解决此问题,但我们可能做得更好。
通过按维度进行卷积(或称为“ DimConv”),卷积会在输入数据的每个维度上发生。
如果张量是D×H×W
,我们可以沿三个可能的轴进行卷积:
H×W
——这是众所周知的深度卷积。输入张量沿通道轴切片,并且filters窗口在空间尺寸(即图像的宽度和高度)上滑动。D×H
——这是宽度方向的卷积。现在,将输入张量沿W
轴切片,并且filters窗口在图像上滑动大小D×H
。D×W
——这是一个高度卷积。输入张量沿H
轴进行切片,并且filters窗口作用于大小为D×W
的图像。
注意:在此博客文章中,我通常C
用来指代通道数,但是论文使用D
(代表深度),因此我也在这里进行了说明。
我们希望这些卷积是轻量级的。通过深度卷积,每个通道都有一个filters。我们对其它两种类型执行相同的操作:
- 宽度卷积在每个x位置都有一个filters
- 高度卷积在每个y位置都有一个filters
这意味着D
深度 filters,W
宽度filters和H
高度filters,因此在D×H×W
DimConv层中总共有 DxHxW filters(通常大小为3×3)。
最后,沿通道尺寸将深度卷积,宽度卷积和高度卷积的输出串联在一起(以交错方式)。
注意:假设我们在边缘周围使用零填充,则深度卷积的输出特征图的大小与其输入相同。对于宽度方向和高度方向的卷积也是如此。如果输入为D×H×W
,则这三种类型的内核中的每一个的输出也为D×H×W
,而concatenate输出张量为3D×H×W
。
一个小细节:宽度和高度卷积取决于输入张量具有特定的宽度或高度。如果希望DimConv层接受任意大小的输入图像,则在宽度和高度卷积之前应有一个上采样(或下采样)层,然后在其后应有一个相应的下采样(或上采样)层。
这是主要构建块的图片,即所谓的DiCE单元(代表高效网络的维数卷积):
![9ce8273f1325c6934c7dcd67c997354c.png](https://i-blog.csdnimg.cn/blog_migrate/e52d679d0bef59f962c38e19fd0ec809.jpeg)
左边是我们刚刚描述的DimConv层。右边是所谓的按维度融合或“ DimFuse”层,它以某种有趣的方式组合了DimConv的结果。
所述DimFuse层替换通常跟随深度方向的1×1层。即使DimConv沿三个不同的轴对信息进行编码,它也是独立进行的,并且我们仍然需要将所有内容混合在一起(类似于ShuffleNet为什么需要通道shuffle)。
DimFuse分两个步骤执行此操作:
- 局部融合。DimConv的三种卷积类型的结果交织在一起
Y_Dim
,因此该张量包含D
组3个切片大小的组H×W
。DimFuse的“局部融合”阶段应用了分组的1×1卷积,它将每组3个切片组合为一个切片。结果Y_G
是张量大小D×H×W
。 - 全局融合。这有两个分支:
i. 底部分支在空间上看事物:它执行常规的深度卷积以独立过滤每个D
通道Y_G
。
ii.最上面的分支着眼于通道:它确定每个通道使用squeeze-and-excitation的重要性。您之前已经看到过这一点:有一个平均池化层将张量的宽度和高度压缩为单个像素,然后是一个全连接的层和一个sigmoid。换句话说,这为Y_G
(,Y_S
)的每个通道计算了一个加权因子。
论文介绍了DiCENet,它实际上只是ShuffleNet v2,但带有DiCE单元。现在,构建基块如下所示:
![0613ed983557b1b3b1922bf5f2efd244.png](https://i-blog.csdnimg.cn/blog_migrate/431d6e7a9ea4cf36a031c3169ac76a96.png)
实际上,您可以采用任何现有的体结构,并将块换成DiCE单元,这样可以更好地工作(他们这样说)。
ImageNet分类精度:
![7b2929bb214b43325fd7b686b8e1d604.png](https://i-blog.csdnimg.cn/blog_migrate/c29f7947c8b04894b2a3d1ba2482e392.png)
分数不错,但没有比我们以前见过的要好得多。
使用1.0比例因子时,在相同数量的参数下,它的性能优于MobileNet v2和ShuffleNet v2。
速度测试(以秒为单位):
![7c7ef7a158229b8067552e55404d41eb.png](https://i-blog.csdnimg.cn/blog_migrate/1896a327f734649de13b45a03d023993.png)
我没有尝试此模型,因为Core ML不支持沿其他轴进行卷积。(而且,我无法导出PyTorch模型。)
可以通过对张量进行置换,进行规则的卷积,然后再次进行置换来完成这项工作,但这似乎很麻烦。(实际上,这就是原始的PyTorch代码所做的。)
结论:一旦有了深度方向的卷积,宽度方向和高度方向的卷积便是一个显而易见的想法,但是我当然不够聪明,无法想到它们,哈哈。
很酷的主意,但就我们的目的而言,似乎不值得这样做,因为它需要Core ML hack才能正常工作。但是,嘿,因为Apple现在拥有Xnor.ai,所以也许我们可以在Core ML 4中沿任意轴进行卷积......
FBNet和ChamNet(2018)
论文1:FBNet: Hardware-Aware Efficient ConvNet Design via Differentiable Neural Architecture Search
论文2:ChamNet: Towards Efficient Network Design through Platform-Aware Model Adaptation
源代码和checkpoints:github.com/facebookresearch/mobile-vision
idea:一种执行神经结构搜索(NAS)的更有效的方法,因此不必分别训练和评估每个潜在的结构。
我的博客文章不是关于NAS的,因此我不会涉及太多细节(而且,关于NAS,我是个菜鸟)。但是显然,进行结构搜索的更快方法使您可以探索其中很大的一部分设计空间!
一个好处是,通过便宜的结构搜索,可以对想要支持的每种类型的设备进行单独搜索成为可能。例如,您可以为iPhone X,iPhone XS和iPhone 11使用不同的模型版本。
FBNet论文主要是关于他们的可微NAS算法,但它也描述了他们发现的几个模型。与本博客文章中提到的许多其它论文不同,本篇论文不是关于发明一种新型的构造块,而是找到了一些将这些块组合在一起的新方法。
所讨论的构造块与MobileNet v2中使用的构造块非常相似:
- 1×1卷积扩展+ ReLU
- depthwise卷积+ ReLU
- 1×1bottleneck层(无激活)
- residual连接(如果输出与输入大小相同)
这里有一些灵活性:第一个1×1卷积层可以将通道数扩展1、3或6倍。depthwise卷积可以是3×3或5×5。两个1×1层都可以使用组卷积。总共有9种可能的结构可供搜索选择。
网络的总体结构是固定的:层数,每层filters数,stride 2的层数等都是预先定义的。搜索仅需选择22层中的哪一层即可获得9个可能的构造块中的哪一个。
通常,网络从单个卷积层开始,然后有几个阶段,每个阶段有四个构造块,最后是最终的1×1卷积。最后,有全局平均池化和分类器层。通过搜索找到除全局池化和分类器以外的所有层。
他们提出了一些结构:
![bb3c03c88f090008989ad371fd338590.png](https://i-blog.csdnimg.cn/blog_migrate/cc5fac002b05d20920260daeec73e14f.png)
彩色框代表构造块的9个变种,其中K =内核大小,E =扩展因子,G =分组卷积。空框(“跳过”)表示此时未使用任何构造块,这实际上是9个选择之一。
因为这种新方法使搜索模型架构变得(相对)便宜,所以您现在可以为要支持的每个设备构建特定的结构,而不必试图提出一个可以在不同设备之间正常工作的架构。
例如,该图显示了FBNet-iPhoneX,它是通过专门搜索在实际iPhone X硬件上最有效的结构而找到的。(搜索过程将针对目标设备上的所有操作使用延迟估计的查找表。请注意,他们为此使用了Caffe2,而不是Core ML。)
ChamNet与FBNet来自同一个人,是另一种有效的结构搜索技术,它使用遗传(进化)算法代替了其他NAS方法使用的更常见的强化学习。
和以前一样,他们不会发明新的构造块,而是使用现有的构造块,这些构造块也是基于MobileNet v2。
主要思想是存在一些基本的神经网络,然后Chameleon系统会搜索适合您所需使用场景的该结构的变种。此方案使用场景是给定目标平台上的延迟和能源与您希望达到的精度的结合。
该方法看起来很酷,但是我需要更详细地研究NAS,然后才能说出任何有用的方法。
ImageNet分类精度:
![658af26bb2cc7f7d22c28f2637a155d4.png](https://i-blog.csdnimg.cn/blog_migrate/9ca66cafe472fb8b3cacacd8534ca1fc.jpeg)
这些模型的性能相当好,可与ShuffleNet v2 +和MobileNet v3媲美。
速度测试(以秒为单位):
![1c101acefaf528cba2d3ded4fe7dce37.png](https://i-blog.csdnimg.cn/blog_migrate/9fcb8002292e483f443a7faf77533adf.png)
测试是针对FBNet-C的。毫不奇怪,它运行速度非常快,因为它具有直接的构造块。在神经引擎上,您可以以MobileNet v2速度获得MobileNet v3级别的准确率。
我无法将ChamNet从Caffe2格式转换为Core ML,因此没有任何度量方法。
结论:除了更好的结构搜索方法以外,这些论文中没有新的层类型。我不确定使用它们的任何预训练模型是否有意义,因为它们是通过针对特定硬件进行优化而发现的。但是,使用他们的搜索方法来找到您自己的结构可能是一个好主意!
也许在某个时候,我们可以在我们的应用程序中捆绑Core ML模型的多个替代方案,并且App Store会自动仅下载针对用户设备的ML ML模型,就像app精简已经对图像所做的一样。
GhostNet(2019)
论文:GhostNet: More Features from Cheap Operations
源代码和checkpoints:github.com/huawei-noah/ghostnet
idea:在卷积层中使用较少的filters可以使其速度更快,但由于最终生成的特征图较少,因此表达力也较低。如果可以通过使用比全卷积便宜的操作来合成额外的特征图来弥补这一点呢?
Ghost模块如下所示:
![ee403436695eae7eb5f15735eb872688.png](https://i-blog.csdnimg.cn/blog_migrate/2f7c50394b3a7501e70bc3b1cb8d6b89.png)
首先,存在常规的卷积,但filters相对较少。它可以具有您想要的任何内核大小。由于此卷积具有有限数量的filters,因此仅生成少量特征图(黄橙色的特征图)。
接下来,使用一系列廉价的线性运算(在图像中显示为ɸ)来从卷积的输出中创建“Ghost”特征。可以使用一个原始特征图来创建多个这些ghost特征图(粉红色的)。
Ghost特征图与未修改的特征图连接在一起,生成此Ghost模块最终输出张量。(这可以通过使ɸ操作之一变成identity函数来实现。)
该技术起作用的原因是,在大型神经网络中,卷积层生成的许多特征图是冗余的,即它们非常相似。这实际上是一件好事(请参阅CondenseNet)。Ghost模块仅以更具成本效益的方式创建这些冗余特征图。
现在,这些线性运算到底是什么?猜猜是什么:depthwise卷积。是的,ɸ 只是depthwise卷积层。
该论文的作者还进行了仿射和小波变换的实验,但是depthwise卷积速度很快,并且可以学习执行许多线性操作,例如平滑,查找边缘等。
因此,尽管名称fancy,但Ghost模块只是常规的卷积,接上depthwise卷积。(这两个之间通常不会有激活函数。)
可以使用Ghost模块替代现有结构中的卷积层。通常,这将提高准确率并降低FLOPS。但是本文还介绍了GhostNet,这是一种基于Ghost模块的有效结构。
GhostNet由Ghost bottleneck组成。这是一个构建模块,由两个连续的Ghost模块组成,它们之间具有ReLU,还有一个residual连接。第一个Ghost模块扩展了通道数量,第二个Ghost模块又减少了通道数量。还有一个strided版本,在两个Ghost模块之间使用stride 2进行depthwise卷积。
在GhostNet使用的Ghost模块中,普通卷积的内核大小为1×1,而线性变换的depthwise卷积使用的内核大小为3×3。对于每个原始特征图,这将生成一个新的ghost特征图。
注意:我发现有趣的是,常规卷积在此处为1×1层。通常情况下,它的大小约为3×3,因此它具有某种感受野。在这里,该卷积层实际上不进行任何过滤,只有depthwise层(ɸ)进行过滤。这有点像一个倒置的MobileNet v1块。
GhostNet的总体结构遵循MobileNet v3,不过当然这些块现在已经成为Ghost的bottlenecks。(它们有时也使用squeeze-and-excitation,而不是hard-swish。)
ImageNet分类精度:
![25db70a5916514449dce22f11c68b286.png](https://i-blog.csdnimg.cn/blog_migrate/2cd99f7bae87e5b0946b98eb24f9b2fb.png)
Paper称他们击败了MobileNet v3。我想说的是,考虑到参数数量时应该算打成平手。
速度测试(以秒为单位):
![488c20733c7bde975dee7980a5dcb2fe.png](https://i-blog.csdnimg.cn/blog_migrate/01c78c4735808c1dda4ad90045ed644b.png)
测试为GhostNet 1.0×。它比MobileNet v3(large)快一点。
结论:速度部分比我的预期要好。但是与MobileNet v3一样,Core ML仅在ANE上运行此模型的一部分,其余部分传递给GPU。因此,它无法充分利用神经引擎(同样,我估计是由于SE层)。
MixNet(2019)
论文:MixConv: Mixed Depthwise Convolutional Kernels
源代码和checkpoints:TensorFlow TPU
idea:实验表明depthwise卷积的内核大小很重要。但是哪个尺寸最好?因此,让我们尝试所有这些!本文介绍了一个新层MixConv,它将多个内核大小放在一个卷积层中。
许多结构在depthwise卷积中使用3×3内核。一些较新的内核也使用5×5内核,甚至使用7×7内核。在一定程度上,较大的内核会提高精度(以增加参数和降低延迟为代价),但是,如本文所述,当内核大于9×9时,精度实际上会变差。
MixConv背后的想法很简单:将通道分成几组,然后对每组应用具有不同内核大小的depthwise卷积。
这有点像Inception模块,除了它发生在单个卷积层内。实际上,MixConv分三个阶段实现:
- 将张量沿通道尺寸分成
G
组 。 - 在每个组上执行不同的depthwise卷积。
- 再次将结果沿通道维度合起来。
通常,MixConv的G
介于1和5之间的值。第i组的卷积使用内核大小2i + 1
。例如,对于三组,内核大小为3×3、5×5和7×7。(如果G
为1,则该层相当于常规的3×3depthwise卷积。)
显而易见的事情是将张量分成相等大小的组,但是本文还尝试了另一种方法,其中较大的内核获得较少的通道数。
MixConv可用作depthwise卷积的直接替代。该论文表明,与3×3卷积相比,在MobileNet v1或v2中使用它会以增加一点参数为代价提高准确率。
还没完。您现在还可以将其放在神经结构搜索(NAS)中,看看是否可以发现一种运行良好的结构。他们使用了与MnasNet和FBNet相似的设置,但是除了基于MobileNet v2块的常规搜索空间外,它还包括MixConv层。
这就是MixNet-S的架构:
![769cc8cd98c9588ba0cfd33860c539f8.png](https://i-blog.csdnimg.cn/blog_migrate/a292f858c9f8bde4655707ce3ff17b3b.png)
如您所见,并非所有层都使用MixConv。显然,结构搜索更喜欢在早期的层中使用较小的内核(以节省计算成本),而在后面的层中使用较大的内核(以提高准确率depthwise)。
还有一层使用非常大的内核。显然,将11×11与常规深度层配合使用会产生非常差的结果,但是在MixConv层内部,效果更好。
ImageNet分类精度:
![297ce16e925203e8cb814d6694ee0f7f.png](https://i-blog.csdnimg.cn/blog_migrate/21063cacfac20d233650fd5e58b11892.png)
真好!这些分数明显优于其它类似规模的模型。
速度测试(以秒为单位):
![801b9eee7c10b1dbeca03c79c7b23b11.png](https://i-blog.csdnimg.cn/blog_migrate/367d9c3f2c7cf9fab4d9247619805dfe.png)
测试适用于MixNet-M。
结论:我认为这不会很快。Core ML中没有native MixConv层。这是通过首先拆分张量,然后并行运行多个depthwise卷积,最后合并结果来实现的。这显然会减慢速度。
EfficientNet(2019、2020)
论文:EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks
源代码和checkpoints:TensorFlow TPU
杰出的工作。EfficientNet正在迅速取代ResNet成为很多深度学习任务的首选骨干。它在ImageNet分类排行榜顶部。
idea:此博客文章中的许多模型都有某种“乘数(multiplier)”,可让您确定每一层有多少个filters。较小的乘数会使模型更快,而较大的乘数会使模型更准确。但这不是扩展convnet的唯一方法。
实际上,可以放大或缩小三种不同的功能:
- 网络宽度:每个卷积层有多少个filters。这就是我刚才提到的。
- 网络深度:模型的每个阶段有多少层。阶段数保持不变,但是可以通过在阶段上添加更多的层来使阶段更深。
- 输入分辨率:输入图像的尺寸。通常使用224×224的图像,但是提高分辨率通常会提高准确率(到一定程度)。
注意:有时人们用“深度乘数”一词来表示“宽度乘数”。他们在谈论单个层的深度,即它具有多少个filters。我认为“通道”或“filters”乘数会是一个更好的说法。对于EfficientNet,深度乘数实际上决定了模型的深度,即模型具有多少层。
提示:即使以一定的输入分辨率训练模型,您通常也可以在运行时使用较小的图像。例如,使用128×224而不是224×224将为模型提供不错的速度提升,此外,它还会保持相机的16:9宽高比,因此您无需裁剪或填充图像。
事实证明,为了有效地向上或向下缩放神经网络,您需要平衡这三件事,因为它们都是相互依赖的。正如EfficientNet论文所述,
“直观上,……如果输入图像更大,则网络需要更多的层来增加感受野,并需要更多的通道来捕获更大图像上的更细粒度的模式(patterns)。”
本文探索了一种新的缩放方法,复合缩放,它使您可以一起缩放网络的深度,宽度和输入分辨率。目标是在使用尽可能少的FLOPS的同时达到最大的精度。
为了使这种缩放方法易于在实践中使用,您只需选择一个缩放因子 ϕ。然后,从中得出深度,宽度和输入分辨率所需的缩放比例量:
- 网络深度按比例缩放
,
- 宽度乘
,
- 和分辨率乘
。
α,β,γ的值是固定的。在论文中,他们使用网格搜索得到α=1.2,β=1.1,γ=1.15。选择这些值使得对于任何新ϕ,FLOPS的总数将增加大约
首先,他们使用神经结构搜索来找到基准网络。这被称为EfficientNet-B0。它与MnasNet非常相似,使用相同MBConv构造块具有3×3和5×5 depthwise卷积,squeeze-and-excitation(SE)以及swish激活。在此结构中没有什么特别新的东西。
EfficientNet-B0的结构如下所示:
![0173ef4008bc0439429ea8a116961a23.png](https://i-blog.csdnimg.cn/blog_migrate/eb3a7923fcf359f445494f68552cc239.png)
EfficientNet-B0是最小的模型(ϕ=1)。接下来,它们用不同的ϕ来扩展模型,从EfficientNet-B1到B7 。所有这些模型,阶段数和构建块的类型都保持不变(上表的F),但是H x W(分辨率), C(宽度),和 L(深度)都变大了。
EfficientNet-B0有5百万参数,所以已经是一个很小的模型。不过他们还有特别的版本针对更小的终端设备。
我们先看看 EfficientNet-EdgeTPU (源码, 博客文章).
EdgeTPU是Google的神经引擎版本。他们使用体系结构搜索对EfficientNet进行了调整,以在EdgeTPU上提供良好的性能。例如,depthwise卷积有时会再次用普通的旧卷积代替,因为事实证明这实际上更快!
他们还去除了swish和squeeze-and-excitation(SE),因为EdgeTPU自然不支持此类操作——正如我们所看到的,神经引擎也是如此。
和以前一样,它们从基准模型EfficientNet-EdgeTPU-S开始,然后使用复合缩放方法生成较大的版本(M和L)。
最后,还有EfficientNet-Lite(源代码,博客文章)。
EfficientNet的“精简版”是在我撰写此博客文章时发布的,时机不错 。model Lite模型不仅针对EdgeTPU进行了优化,同时还应该在移动CPU和GPU上运行良好。
与Edge模型一样,EfficientNet-Lite没有SE。Swish被ReLU6取代,主要是因为这样可以更轻松地量化模型权重。
根据发行说明,他们还“在放大模型时固定了主干和头,以减小缩放模型的大小和计算量。” 我不确定他们在那里做了什么,但是我认为它类似于MobileNet v3,后者简化了模型的第一层和最后一层,因为它们相对昂贵。
有五个版本:EfficientNet-Lite0到Lite4,其中0是最小的,而4是最大的。如同所有EfficientNet模型一样,较大的模型是通过扩大基准模型生成的。
注意:值得一提的是EfficientNet的其它一些变种。CondConv: Conditionally Parameterized Convolutions for Efficient Inference引入了新层CondConv,该层将EfficientNet的准确率提高了几个百分点。卷积内核现在具有不同的权重集,它使用的权重取决于输入张量。有趣的想法,但是这样做的运行时成本相对准确率的提升可能不值得。Adversarial Examples Improve Image Recognition介绍了EfficientNet-B8,这是一种使用对抗样本进行训练的超大型模型。Self-training with Noisy Student improves ImageNet classification引入EfficientNet-L2并在庞大的数据集上使用伪标签对其进行训练。使用此方法训练的EfficientNet模型目前位于ImageNet排行榜的顶部,top-1的准确率超过88%,top-5的准确率超过98%。令人印象深刻,但超出了移动使用范围。
ImageNet分类精度:
![62168542c947e93a76f293bf63c201fb.png](https://i-blog.csdnimg.cn/blog_migrate/bb72c33611eeef05ab49f520b8b6e4c7.jpeg)
我没有包含较大的版本,因为它们具有更多的参数,因此不适合移动设备。
除了最小的Lite模型外,所有这些模型的得分均高于ResNet-50,并且参数和FLOPS更少。令人印象深刻。
请注意,对于相同数量的参数,Lite模型的准确率比常规模型差。这清楚地表明,squeeze-and-excit和swish肯定会对准确率产生积极影响,但是,现在它们在移动设备上不行。
注意: EfficientNet模型越大,则预期输入图像就越大。对于B0和Lite0,它是224×224像素,对于B1和Lite1,它是240×240,依此类推。对于最大的型号B7,它是600×600像素。
速度测试(以秒为单位):
![549fb2b98e97b298b2caa2d451631d2e.png](https://i-blog.csdnimg.cn/blog_migrate/5f6e5336664b7be23317be440fb3b5cb.jpeg)
毫不奇怪,EfficientNet-B0无法充分利用神经引擎,因为SE涉及广播乘法。Lite没有SE,因此在ANE上速度更快。
结论:对于CPU和GPU,B0和Lite之间的速度差异很小,因此您最好使用B0以获得更好的精度。但是,如果您打算使用神经引擎,则肯定要选择Lite版本之一。
结束
因此……如果您要构建一种新的模型以在iPhone或iPad上使用,应将哪种结构用作骨干网络呢?
我一直是MobileNet v1和v2 的忠实拥趸,我仍然认为他们是不错的选择。不幸的是,v3有点令人失望,因为它在神经引擎上的性能很差。
其它许多新模型在ANE上的效果也令人失望。
EfficientNet是最好的模型之一,由于名气大,我认为很多人会开始使用它。在速度上,它没有给我留下深刻的印象——它不是最慢的模型,但也不是最快的模型。
我的结论是:
- MobileNet v3是CPU和GPU的最佳选择。
- FBNet-C是神经引擎的最佳选择。
这两个选择在精度和速度之间取得了很好的平衡。如果可以以稍微慢一些为代价获得更高的准确率,请选择EfficientNet-Lite。