
极市导读
本文首先对模型压缩进行了综述,论述目前深度学习存在的挑战,同时对三种高效自动机器流水线方法ProxyLessNAS、AMC和AMC进行了详细的介绍。最后探讨了如何进行网络体系结构、剪枝和量化策略的联合搜索。>>周二直播!田值:实例分割创新式突破BoxInst,仅用Box标注,实现COCO 33.2AP!
目录
-
为什么要进行Model Compression?
论述当前深度学习存在的挑战。
-
自动机器学习流水线 (AutoML Pipeline):让模型更加高效
简述自动机器学习的流水线。
第1步:ProxyLessNAS:搜索最适宜的模型架构。
第2步:AMC:压缩模型,减少参数量。
第3步:HAQ:进一步量化模型,减小内存占用。
-
自动机器学习流水线的演进
论述如何进行网络体系结构、剪枝和量化策略的联合搜索。
1 为什么要进行Model Compression?
摩尔定律告诉我们:芯片的性能每隔18个月将会提高一倍。
尽管摩尔定律的现象已经被观察到了数十年,但是,它仍应该被视为一种对现象的观测或对未来的推测,而不是一个物理定律。
换句话说,未来的增长率在逻辑上无法保证会跟过去的数据一样,也就是逻辑上无法保证摩尔定律会持续下去。而且,摩尔定律已经在2013年年底放缓。
比如说英特尔在22纳米跟14纳米的CPU制程上已经放慢了技术更新的脚步,之后的时间里,晶体管数量密度预计只会每3年增加一倍。
而另一方面,在现代深度学习中,更复杂的问题往往需要更复杂的计算量来处理;摩尔定律的放缓使得当前的算力往往无法满足复杂AI问题的要求,尤其是在移动端这种算理有限的设备上面。
评价一个深度学习模型,除了Accuracy之外,我们还要考虑下面这5个方面:
-
延迟:Latency (ms) -
能耗:Energy Consumption (J/度电) -
计算量:Computational Cost (FLOPs/BitOPs) -
模型参数量:Parameter (M) -
运行占用内存:Memory (MB)
所以当前深度学习面临的一个挑战是:模型非常大 (Large Model Size),也就需要大量的能源消耗 (Large Energy Consumption),密集的计算量 (Computation Intensive)和密集的内存占用 (Memory Intensive)。以上问题使得模型在部署的过程中会遇到很大的挑战。
举一个例子: AlphaGo打一局比赛约需要1920块CPU和280块GPU的算力,以及3000$的电费(electric bill),对于端侧设备 (Edge-side devices)来讲,会很快耗尽电池的电量 (Drains Battery);对于数据中心来讲会增加总持有成本TCO (Total Cost of Ownership)。
所以,模型压缩对于深度学习的部署来讲意义重大,尤其是硬件资源受限的端侧设备。
模型压缩的方法有很多,可以参考下面的链接:
深入浅出的模型压缩:你一定从未见过如此通俗易懂的Slimming操作
科技猛兽:模型压缩工作总结
https://zhuanlan.zhihu.com/p/262359207
借助AutoML技术,可以使得深度学习模型变得更加高效,以部署在端侧设备上面。所以本文介绍的重点是这一流水线具体是什么样的,以及后续有哪些改进的工作。
2 自动机器学习流水线 (AutoML Pipeline):让模型更加高效
-
2.1 自动机器学习的流水线
自动机器学习流水线是指基于自动机器学习(AutoML)完成模型的优化过程。
输入: 模型要部署的目标硬件设备。约束条件(Latency,Energy Consumption,Model Size,Memory,FLOPs等)。
输出: 部署的模型。
中间过程:
AutoML搜索最适宜的模型架构,最大化精度。
对这个模型进行压缩,减少参数量。
对压缩后的模型进行量化,进一步减少内存占用。
-
2.2 第1步:ProxyLessNAS:搜索最适宜的模型架构
MIT: ProxyLessNAS: Direct Neural Architecture Search on Target Task and Hardware
刚才讲到,当把模型部署在手机,头盔,智能手表,手环等移动端设备的时候,我们不仅希望模型的准确度高,还希望它具有低的延迟和低的耗电量。以往的做法是将相同的模型不加改进而直接部署在多种设备上面,比如下图:
这种做法的优点是简单快捷,不需要任何额外的设计成本;但是这种做法的缺点是没有考虑到不同硬件设备之间的差异性:比如GPU的并行度 (Degree of Parallelism)比CPU要高,cache size更大,内存带宽 (Memory bandwidth,单位时间里存储器所存取的信息量,也称为存储器在单位时间内读出/写入的位数或字节数)性能也有不同。因此使用同样的模型得到的结果往往是次优的。
ProxyLessNAS解决的就是这个问题,即希望针对不同的硬件设备专业化神经网络模型,以在目标硬件设备上面获得更好的准确率和较高的硬件效率。
为每个硬件设计专门的深度学习模型代价是十分高昂的,往往需要请一个组的深度学习专家来进行模型设计和调参,显然是无法承受的。于是我们考虑使用AutoML的方法,自动化地设计神经网络的模型,来替代人类专家进行神经网络架构的设计,一定程度上能够解决人力资源不足的问题。
但是,神经架构搜索的成本是十分高昂的,谷歌提出的NASNet在小规模数据集CIFAR-10上面搜索一次所需要的时间,换算成单块GPU大约需要5年。所以,考虑到这样巨大的计算资源的要求,之前的神经架构搜索算法大多采用基于代理 (Proxy)的方法。
代理任务 (Proxy Task)相比于目标任务 (Target Task),一般具有:
-
更小的数据集 (e.g. CIFAR→ImageNet) -
训练更少的epochs -
更小的搜索空间 -
使用更浅的模型。
总之,代理任务相当于是目标任务的缩小简化版。之后,把代理任务搜索得到的结果迁移到目标任务上面,如下图所示:
这样做的问题有3点:
-
在代理任务上搜索得到的最优结果在目标任务上是次优的,尤其是当考虑Latency时。 -
需要堆叠重复的单元,限制了块的多样性,从而降低了性能。 -
不能根据目标任务的实际硬件要求进行优化。
ProxyLessNAS提出的动机就是为了解决以上的3点限制,作者希望能直接在目标任务和硬件 ( target task and hardware)上搜索出最优模型的架构,而避免使用代理Proxy,这解决了上面的第1个问题。同时,ProxyLessNAS不去堆叠重复的单元,每个block都可以被搜索,这解决了上面的第2个问题。最后,ProxyLessNAS还能考虑目标硬件的Latency,这解决了上面的第3个问题。ProxyLessNAS实现的结果如下图:
首先简述ProxyLessNAS的做法:
把NAS的过程视为路径级剪枝的过程 (Path-level Pruning)。首先训练一个包含所有的操作的超网络 (over-parameterized network)。每个操作有自己的二值化架构参数和权重参数,并采样梯度下降的方法训练二值化的架构参数,那些架构参数比较低的操作到最后将会被剪掉。
在训练这个超网络的时候,由于操作数量很多,会导致GPU显存不足 (GPU memory explosion),这个问题很常见,因为GPU显存会随着候选操作的数量呈线性增长。解决的办法是每次只激活一条路径进行训练,即:每个操作的架构参数是二值化的。每次更新参数时,只允许一个操作处于激活状态。这样一来,GPU的显存的需求的复杂度就会从 变为 。
在One-Shot NAS方法中:
在DARTS方法中:
二值化就是每次只激活一条路径,表达式是:
图7所表达的含义就是每次只激活一条路径进行更新参数。具体怎么更新呢?
-
首先取一个batch的数据,根据 式采样出一个 ,这时候就相当于只激活了一条路径,其他未被激活的路径的参数被freeze了。 -
使用training set 来update采样的这条路径的参数,如上图左所示。 -
再根据 式采样出一个 ,使用validation set 来update架构参数,如上图右所示。 -
上述3步迭代执行。
更新架构参数时,首先要明确这里的架构参数是什么?答案是: ,这些 通过 的操作得到 ,再通过采样得到 ,最后, 再参与计算图。所以,在反向传播时,我们手里有的只是 。可我们要计算的是 。
那么具体的方法是:
在反向传播时,以上所有的参数都已知了,于是可以求出 。
但这样做也存在一个问题,即你需要保存所有的 ,使得GPU memory变成了 ,即显存使用量依然与 相关。
为了解决这个问题,作者采取的做法是:
-
首先根据(3)式sample出2条路径,屏蔽其他的路径,这样强制使得 。 -
采样之后, 和 将会被重置。 -
根据(4)式更新这2条路径的架构参数 ,更新完后,乘上一个系数,保持二者之和不变,即始终保持未被采样的路径的架构参数之和不变。
一个采样路径被增强(路径权重增加),另一个采样路径被衰减(路径权重降低),而所有其他路径保持不变。以这种方式,不管 的值如何,在架构参数的每个更新步骤中只涉及两条路径,从而将存储器需求降低到训练紧凑模型的相同水平。
说白了,就是我更新架构参数的时候不更新所有的架构参数,只采样2条路径,更新这2条路径的架构参数,同时保持未被采样的路径的架构参数之和不变。
除此之外,为了解决第3个问题,就必须把延迟Latency作为目标函数要考虑的部分。但是,Latency这个指标是不可微分的 (non-differentiable),因此,得想个办法把Latency这东西变得可微分。
做法是:首先在目标硬件上收集各种候选操作的延迟Latency,构成一个数据集,去搭建一个延迟预测的模型。这样一来,基于这个模型就可以获得网络的延迟预测期望值。这个期望值就可以作为一个正则项,整合到损失函数当中,通过梯度进行直接的优化。
假设网络一共有 个Block,对于第 个Block来讲,我们求出它的Latency的期望值:
式中的 表示第 个候选操作。 表示这个predictor的预测值。
在反向传播求微分时,表达式就变为了:
而式中的 是已知的。
最后,总的网络的Latency可以写成:
这一流程可以表示为图8:
损失函数为:

