深度向手机端神经网络进发MobileNet压缩指南.docx

上传人:b****7 文档编号:10174478 上传时间:2023-02-09 格式:DOCX 页数:9 大小:21.54KB
下载 相关 举报
深度向手机端神经网络进发MobileNet压缩指南.docx_第1页
第1页 / 共9页
深度向手机端神经网络进发MobileNet压缩指南.docx_第2页
第2页 / 共9页
深度向手机端神经网络进发MobileNet压缩指南.docx_第3页
第3页 / 共9页
深度向手机端神经网络进发MobileNet压缩指南.docx_第4页
第4页 / 共9页
深度向手机端神经网络进发MobileNet压缩指南.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

深度向手机端神经网络进发MobileNet压缩指南.docx

《深度向手机端神经网络进发MobileNet压缩指南.docx》由会员分享,可在线阅读,更多相关《深度向手机端神经网络进发MobileNet压缩指南.docx(9页珍藏版)》请在冰豆网上搜索。

深度向手机端神经网络进发MobileNet压缩指南.docx

深度向手机端神经网络进发MobileNet压缩指南

深度向手机端神经网络进发:

MobileNet压缩指南

选自MachineThink作者:

MatthijsHollemans机器之心编译

随着MobileNet等面向移动设备的模型不断出现,机器学习正在走向实用化。

不过,由于深度学习等方法需要消耗大量计算资源的因素,目前我们距离真正的移动端人工智能应用还有一段距离。

在硬件之外,我们也需要对模型本身进行压缩,最近,荷兰工程师MatthijsHollemans向我们展示了他压缩MobileNet的方法:

通过删除卷积层的部分滤波器,他在保证准确性不变的情况下,让模型体量缩小了25%,让我们看看他是怎么做的。

随着机器学习技术向移动设备渗透的趋势,人们正在越来越注重于寻找让深度神经网络更快、更简洁的方式。

一种方法是提出更智能化的神经网络设计。

例如:

MobileNet可以在获得相同结果的情况下比VGG-16小32倍,速度快上10倍。

另一个方法是采用现有的神经网络,并用删除与结果无关的神经元的方法来压缩它。

本文会着重介绍这种方法。

我们将着手改进MobileNet-224,让它的体量减小25%,换句话说,我们要把它的参数从400万个减少到300万个——同时不损失模型的准确性(好吧…只有一点点)。

如何做到更好

鉴于MobileNet比VGG16要小32倍,而准确性相同,前者捕获知识的效率显然更高。

的确,VGG模型中的神经网络连接比我们所需要的多很多。

斯坦福大学韩松等人2015年在论文《DeepCompression:

CompressingDeepNeuralNetworkswithPruning,TrainedQuantizationandHuffmanCoding》中提出的压缩网络方法展示了通过剪枝不必要的神经网络连接让VGG16缩小49倍,并保持准确性的方法。

现在问题来了:

MobileNet里还有不必要的连接接吗?

即使这个模型已足够小,但我们能不能让它变得更小且不损失准确性呢?

当你试图压缩一个神经网络,需要权衡的问题是模型尺寸与准确性。

通常,网络越小,速度就越快(当然也耗电更少),但预测出来的结果也会越差。

例如,MobileNet的性能要好过SqueezeNet,同时前者也比后者大上3.4倍。

在理想情况下,我们总是希望找到尽可能小的神经网络——不过它们必须为我们传递准确的结果。

这在机器学习中是一个开放问题,在正确的理论出现之前,让我们先试着从大模型开始剪枝吧。

在这个项目中,我使用了Keras2.0.7版中预训练的MobileNet,并运行在TensorFlow1.0.3上。

如果使用ImageNetILSVRC2012验证集来测试,它的得分是:

Top-1accuracyover50000images=68.4%Top-5accuracyover50000images=88.3%这意味着它有68.4%的几率一次性给出正确结果,如果范围扩大到排名前五的结果,则准确率则为88.3%。

我们希望压缩这个模型,并让它保持以上分数。

注意:

MobileNet论文(MobileNets:

EfficientConvolutionalNeuralNetworksforMobileVisionApplications)声称它在ImageNet上的准确率是70.6%,VGG16是71.5%,GoogleNet是69.8%。

我们还不知道这个数据是来自ImageNet还是验证集。

无论如何,Keras版的MobileNet在验证集上的得分是68.4%,我们将会使用这个数字作为基准。

如何压缩一个卷积神经网络

就像多数的现代神经网络一样,MobileNet有着许多卷积层。

将每层的权重由小至大排列并剔除带有最小权重的连接就是一种压缩卷积层的方法。

这种方法是由Han等人在将VGG压缩49倍时提出的。

听起来是个好方法但也存在着大缺陷:

它造成了稀疏连接。

不幸的是,GPUs并不擅长处理稀疏矩阵,并且在计算上花费了更多的时间,尽管网络得到了压缩,你并未由此而省时。

在这种情况下,压缩得更小并不意味着会更快。

但这对于追求魔鬼速度的我们并不奏效:

小而快才是我们所追求的。

我们将移除复杂的卷积滤波器,而不是修剪掉单个连接。

这让我们保持连接紧密的同时也不会给GPU带来麻烦。

回想一下一个卷积层产出一个带有一组特定数量的输出通道的图像。

每一个输出通道都包含了单一卷积滤波器带来的影响。

这样一个滤波器接管了所有来自于输入通道的加权和,并将这一加权和写入单一的输出通道。

我们要找出那种最不重要的卷积滤波器,并且将其输出通道从层中移除。

例如,MobileNet中的层conv_pw_12有1024个输出通道。

我们会舍弃这其中的256个通道使得被压缩版的conv_pw_12只有768个输出通道。

注意:

为了迎合Metal,我们应该以每次移除四个输出通道的速度进行。

因为Metal实际上是一个图形API,它用纹理(texture)来描述神经网络的图像数据,而每一个纹理为四个连续的通道保存数据。

所以,如果我们只移除一个输出通道,Metal仍然需要处理其他三个通道的纹理。

考虑到Metal的这一特点,我们只有以四的倍数来移除通道才会使得压缩层有意义。

现在问题是:

我们可以移除哪些滤波器和输出通道?

我们仅希望在不影响太多性能的情况下移除一些输出通道。

我们可以使用不同的度量方案来估计滤波器的相关性,但是我们也可以选择非常简单的方法:

滤波器权重的L1范数,即所有滤波器权重的绝对值之和。

例如以下是MobileNet前面几个卷积层(32个滤波器)的L1范数:

如图所示,L1范数非常小、接近于零的第一个层有10个滤波器。

我们或许可以去除这些滤波器。

但是由于我们的目标是使用带有Metal的网络,因此去除10个滤波器没有意义。

我们必须去除8个或12个滤波器。

我首先尝试去除8个最小的滤波器。

效果很好,准确率完全没有损失,因此我决定去除12个。

稍后你可以看到,它的效果依然很好。

这意味着我们实际上能够去除该网络第一个卷积层中37.5%的滤波器,而网络性能不会变差!

这里有MobileNet所有卷积层的L1范数示图。

你可以看到很多层的滤波器对网络几乎没有贡献(低L1范数)。

注:

由于并非所有层都具备相同数量的输出通道,上图中所有数据都按同样的标准进行归一化处理。

横轴代表通道(按L1范数的值从低到高),纵轴代表实际的L1范数(同样是归一化处理后的)。

你可以在Lietal所写的论文《PruningFiltersForEfficientConvnets》中获取该方法的更多详情。

从一个层中去除滤波器意味着该层输出通道的数量变少。

自然而然,这对该网络下一层也有影响,因为下一层现在的输入通道变少了。

因此,我们还必须从那一层去除对应输入通道。

当卷积之后是批量归一化(BN)时,我们还必须从批量归一化参数中去除这些通道。

MobileNet事实上有三种卷积层:

一个常规的3×3卷积(第一层)Depth-wise卷积1×1卷积(又名pointwiseconvolution)

我们仅从3×3和1×1卷积中去除滤波器,而非Depth-wise卷积。

一个Depth-wise卷积必须具备相同数量的输出通道和输入通道。

压缩可能没有什么收获,而且Depth-wise卷积很快(因为它们的工作比常规卷积要少)。

因此我们主要将注意力集中在带有3×3和1×1卷积的层。

再训练

因为从层中删除滤波器会让网络的准确性变差——毕竟,你在丢弃神经网络学习到的东西,即使它可能不是非常重要——你需要做一点重新训练,这样才能弥补丢弃造成的损失。

在训练意味着你需要再次调用model.fit()。

一点小小的试错后,我们就会把学习率定在0.00001——一个非常小的数字,任何稍大的训练参数都会让结果超出控制。

学习率如此之小的原因是,在这里,大部分网络已经被训练过了,我们只想进行小改进来提升结果。

过程是这样:

1.在层中4倍并行地移除滤波器(即输出通道)2.再训练该神经网络几个epoch3.对验证集进行评估,以检查该神经网络的准确性是否恢复至之前水准4.移动到下一层并重复这些步骤

正如你所看到的,这个过程费时费力,因为我们每次只能改动一层,而修改之后每次又要重新训练神经网络。

每个层中,可以丢弃的滤波器都是不太一样的。

使用训练子集

MobileNet已在ILSVRC比赛数据集(也就是ImageNet)中进行过预训练了。

这是一个巨大的数据集,其中包含超过120万张训练图片。

依靠最近装配的深度学习机器(只有一块英伟达GTX1080Ti的Linux系统),每个epoch需要训练两小时之久。

即使用5万张图像验证集来做这件事也需要3分钟。

毫无疑问,这样的硬件让快速迭代变得难以实现。

我可不想每天盯着屏幕两个小时,只为看到模型出现一点点小变化。

所以我们得在样本上找办法,而不是用完整的数据集,我在数据集1000个类别中每类随机找出五张图片(这多少有点代表性),形成了5000张图片的训练子集。

现在每个epoch只需要30秒钟了。

这要比两个小时方便多了!

为了进行验证,我从完整验证集中随机抽取了1000张图片作为验证集,用它来评估网络性能只需要画上3秒钟。

看来,使用样本的方法很有效。

压缩第一个卷积层

如你所见,第一个卷积层有10个非常小的L1规范滤波器。

因为对于Metal,我们需要以4的倍数来去除滤波器,所以我删除了具有最小L1规范的12个滤波器。

最初,我还没有从神经网络中删除任何滤波器,只是将他们的连接权重设置为0。

理论上,这样的事情可以让Top-1准确率从69.4%降到68.7%——有一点损失,不过没有什么不是在训练不能解决的。

接下来,我创建了一个与原始层相同的新模型,并在这里删除了滤波器,所以在第一个卷积层中,实际上只有24个输出通道(而不是原来的36个)。

但是现在准确率评分变得很低了:

29.9%,发生了什么?

理论上,将连接权重设置为0和删除连接应该可以获得相同的结果,但实践中却出了差错:

我忘了将下一层相应输入通道的权重设置为0。

而更糟的是,因为下一层是深度卷积,我还得设置相应的参数,让该层的批量归一化为0。

教训:

从一层中去除滤波器也会对其它层产生影响。

而这些变化会影响评分。

所以删除第一层中的滤波器损失37.5%的准确率不太值得?

在检查整个模型后,我发现问题在于第二个批量范数(batchnorm)层上12个偏置值:

当它们变成其他任何数字后,其他的东西都归零了。

看起来,是这12个数字让68.7%的识别率变成了29.9%,真的吗?

这个神经网络有400万个参数,12个数字肯定不能决定一切,在这样的思路下,我觉得我可以做点什么了。

我用5000张图片的子集重训练了神经网络10个epoch(只用了五分钟),现在准确率重新回到了68.4%,这虽然不及原模型(69.4%),但已经很接近了。

一点样本图像就让准确率回到了65%以上,这太简单了,请记住:

我们用于重训练的样本大小只有整个数据集的0.4%。

我认为,如果这样一点图像就可以让分数大体回复,那么整个数据集的训练应该可以让准确率完全回归原水平。

注解:

使用相同的样本进行长时间训练可不是什么好主意。

当你用同样的子集训练10个epoch之后,神经网络就会严重过拟合。

所以在使用了10个epoch之后,你得换一个新的训练子集。

现在,第一卷积层减少了37.5%的权重,这听起来不错,但是这只是小小的一层而已。

它只有三个输入通道与32个输出通道(削减后为24个)。

总共节省的参数是:

3×3×3×12=324,效果太不明显了,不过这是一个好的开始。

最后的PW卷积层

在压缩第一层后,我们可以考虑压缩分类层之前的最后一个卷积层。

在MobileNet的Keras版中,分类层也正好是一个卷积层,但是我们不能从这一卷积层中移除任何通道。

因为这个网络是在ImageNet中训练的,该数据集有1000个种类,因此分类层也必须有1000个输出通道。

如果我们删除了任何通道,那么模型就不能再对这些类别做预测。

conv_pw_13层有1024个输出通道,虽然并没有理论依据,但我们可以先尝试移除256个。

conv_pw_13层有104.8576万个参数,它在整个网络中都是最大的层,因此我们可以对它执行多一点的压缩。

这一层的L1范数如下所示:

从上图来看,移除256个通道可能有点多,留待观察。

再一次,我们移除了网络层的输出通道,然后是批规范化层,然后调整下一层,因为它们也有一些输入通道。

移除256个通道,不止为conv_pw_13节省了1024×1×1×256=262,144个参数,也为分类层移除了256,000个参数。

在压缩完conv_pw_13层之后,验证得分掉到了60.7%(top1)和82.9%(top5)。

也没多糟糕,特别是考虑到还没再训练。

在样本上再训练10个epochs之后,准确率提升到了63.6%。

在新的训练样本上再多训练10个epochs之后,提升到了65.0%(top1)和86.1%(top5)。

对10分钟的训练来说,不错了。

得到0.65的得分我已经很开心了,能够继续修剪其他的层。

虽然还没得到最初的得分,但已经证明网络成功地补偿了修剪的连接。

更多层&真实再训练

接下来,我使用同样的方法修剪conv_pw_10(移除了512个滤波器中的32个)和conv_pw_12(移除了1024个滤波器中的256个)。

在每个新的网络层上,我发现要得到之前的标准准确率越来越难。

在conv_pw_10之后准确率是64.2%,conv_pw_12之后只有63.4%。

每次我使用不同的训练样本,只是为了确保结果仍旧具有代表性,模型不会过拟合。

在pw_10与pw_12之后,我做了conv_pw_11。

其实在选择压缩层上我没有总体规划,是随机选择的。

在conv_pw_11上,我修剪了512个滤波器中的96个。

在其他层上,我最多修剪掉滤波器个数的25%,部分是基于L1-norms所获得的信息进行修剪,但主要是因为它是很好的约整数。

但是,移除128个滤波器导致准确率下降太多,再训练也无法提升到60%以上。

只剪除96个滤波器有更好的结果,但再训练之后得分也只是61.5%。

在验证得分如此令人失望的情况下,无疑是我过于激动,移除了太多的滤波器,导致神经网络不再能够学习ImageNet。

所有的再训练都是在5000张图像的小样本上进行的,所以修剪过的网络只是在所有训练集上的一部分再训练的。

时间限制了网络只能在全部训练集上运行几轮。

在1个epoch之后,准确率达到66.4(top1)、0.87(top5)。

我并未使用数据增强,只使用了原始的训练图像。

既然已经开始,我决定多训练几个epoch,看看会有什么不同结果。

在第二个epoch之后,网络得分是67.2(top1)、87.7(top5)。

之后,我又在完整训练集上训练了更多的epochs,且加入了数据增强,用了更小的学习率。

不幸的是,这对结果改善毫无益处。

于是,我停止了实验,时间不够。

在多训练几轮,我保证有很大可能把网络再次压缩。

而且,还有9个pw卷积层我们还没处理,我保证这些层也能修剪掉一些滤波器。

结论Originalnetworksize:

4,253,864parametersCompressednetworksize:

3,210,232parametersCompressedto:

75.5%oforiginalsizeTop-1accuracyover50000images=67.2%Top-5accuracyover50000images=87.7%以上结果未能达到我的预期目标:

网络确实压缩了25%,但准确率有点差,虽然准确率没有损失25%。

因为我顾及的是整个流程,所以该工作流中有些地方可以改进。

在选择需要移除的滤波器上,或者压缩网络层的顺序上,我做的也不科学。

但对该项目而言,足够了,我只是想要获取可能压缩神经网络的思路。

可以明显看到,我未能做到对网络的最优修剪。

使用L1-norms可能不是确定滤波器重要度的最佳方式。

也可能一次性只移除一些滤波器,而非砍掉网络层输出通道的1/4,这样会更好一些。

我很开心使用的样本在再训练中表现非常好,不需要几个小时进行再训练,这意味着我能快速的进行新实验。

这件事是否值得做呢?

我觉得是。

假设你有一个神经网络在手机端运行需要25FPS,意味着每帧需要0.04秒的处理时间。

如果网络压缩了25%,假设这意味着处理速度快了25%,也就是每帧的处理时间为0.03秒,节约了很大的时间。

在运行流畅与运行不畅的APP上,可能会有细微差别。

原文地址:

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1