文章发布于公号【数智物语】 (ID:decision_engine),关注公号不错过每一篇干货。
来源 | AI科技评论(id:aitechtalk)
原标题 | Pruning Deep Neural Networks
作 者 | Ranjeet Singh
翻 译 | had_in(电子科技大学)
编 辑 | Pita
目前,深度学习模型需要大量的计算、内存和功耗,这成为我们在实时推理或在计算资源有限的边缘设备以及浏览器上运行模型的瓶颈。能量效率是当前深度学习模型的主要关注点。提升这种效率的方法之一是着眼于推理效率。
更复杂的模型=>更多的内存消耗=>更多的功耗
剪枝就是一种推理方法,它可以有效地获得更小的模型、更高效的内存、更高效的功率和更快的推理,同时在精度上损失较小,其他类似的技术还有权值共享和量化。深度学习的灵感来自于神经科学领域的几个方面。
随着深度学习的进步,最先进的模型也变得越来越精确,但这种进步是有代价的。
01
挑战一:模型尺度变得越来越大
很难通过空中下载技术来分配大尺度模型。
Dally, NIPS 2016年深度神经网络高效方法研讨会
02
挑战二:速度
训练时间以fb.resnet.torch为基准,基于M40 GPUs。
如此长的训练时间限制了机器学习研究人员的效率。
03
挑战三:能量效率
AlphaGo: 1920个cpu和280个gpu,每场比赛3000美元的电费
1. 在移动设备上:快速耗尽电池电量
2. 数据中心:增加成本
04
解决方法 — 高效的推断算法
1. 剪枝
2. 权重共享
3. 量化
4. 低秩逼近
5. 二值神经网络 / 三值神经网络
6. Winograd转换
05
生物学启发的剪枝算法
人工神经网络中的剪枝被认为是来自人类大脑突触修剪的一个想法,在人类大脑中,当轴突和树突完全衰退和死亡,会导致突触消失,这发生在许多哺乳动物的幼年早期和发育期初期之间。突触修剪从出生时开始,一直持续到25岁左右。
06
深层神经网络剪枝
[Lecun等. NIPS,89] [Han等. NIPS’15]
网络通常看起来与左边的那个类似:下层的每个神经元都与上层每个神经元相连,但这意味着我们需要将许多浮点数相乘。理想情况下,我们只需要将每个神经元连接到其他的几个神经元上就可以省去一些乘法;这就是所谓的“稀疏”网络。
稀疏模型更容易压缩,而且我们可以在推断时跳过0值以改进推断延迟。
如果可以根据神经元的贡献大小对网络中的神经元进行排序,那么就可以将排名较低的神经元从网络中移除,从而得到一个更小、更快的网络。
获得更快/更小的网络,对于在移动设备上运行这些深度学习网络非常重要。
例如,可以根据神经元权重的L1/L2范数进行排序。在修剪之后,准确性会下降(如果排序较合理,可则能不会下降太多准确率),并且网络通常是迭代地训练-修剪-训练-修剪以较大程度保证模型的准确率。如果我们一次修剪得太多,网络可能会受到严重破坏,无法恢复准确率。因此在实践中,这是一个迭代的过程——通常称为“迭代剪枝”:修剪/训练/重复。
请参阅Tensorflow团队编写的代码,以了解迭代剪枝。
07
权重修剪
将权重矩阵中的单个权重设置为零。这相当于删除连接,如图所示。
为了实现k%的稀疏性,我们将权重矩阵W中的各个权重按大小排序,然后将最小的k%的部分权重设置为零。
1. f = h5py.File("model_weights.h5",'r+')
2. for k in [.25, .50, .60, .70, .80, .90, .95, .97, .99]:
3. ranks = {}
4. for l in list(f[‘model_weights’])[:-1]:
5. data = f[‘model_weights’][l][l][‘kernel:0’]
6. w = np.array(data)
7. ranks[l]=(rankdata(np.abs(w),method=’dense’) — 1).astype(int).reshape(w.shape)
8. lower_bound_rank = np.ceil(np.max(ranks[l])*k).astype(int)
9. ranks[l][ranks[l]<=lower_bound_rank] = 0
10. ranks[l][ranks[l]>lower_bound_rank] = 1
11. w = w*ranks[l]
12. data[…] = w
08
单元/神经元修剪
将权重矩阵中的整个列设置为零,实际上是删除相应的输出神经元。
为了达到k%的稀疏性,我们根据权重矩阵的l2范数对列进行排序,并删除最小的k%的列。
1. f = h5py.File("model_weights.h5",'r+')
2. for k in [.25, .50, .60, .70, .80, .90, .95, .97, .99]:
3. ranks = {}
4. for l in list(f[‘model_weights’])[:-1]:
5. data = f[‘model_weights’][l][l][‘kernel:0’]
6. w = np.array(data)
7. norm = LA.norm(w,axis=0)
8. norm = np.tile(norm,(w.shape[0],1))
9. ranks[l] = (rankdata(norm,method=’dense’) — 1).astype(int).reshape(norm.shape)
10. lower_bound_rank = np.ceil(np.max(ranks[l])*k).astype(int)
11. ranks[l][ranks[l]<=lower_bound_rank] = 0
12. ranks[l][ranks[l]>lower_bound_rank] = 1
13. w = w*ranks[l]
14. data[…] = w
当然了,当您想增加稀疏性并删除更多的部分网络时,模型性能将逐步下降。您估计稀疏性与性能之间的退化曲线是什么样的呢?
利用一个简单的神经网络结构对MNIST数据集上的图像分类模型进行剪枝 ,如下:
引用的参考代码中使用的体系结构
使用代码重新生成的退化曲线图
09
关键要点
许多研究人员认为剪枝是一种被忽视的方法,但它将得到更多的关注,并在实践中更多地使用。我们展示了如何使用一个非常简单的神经网络结构在一个简单数据集上获得良好的结果。我认为在实践中利用深度学习来解决的许多问题都与此类似,在有限的数据集上使用迁移学习,因此这些问题也可以从修剪算法中受益。
10
参考
1. Code for this blog post(https://drive.google.com/open?id=1GBLFxyFQtTTve_EE5y1Ulo0RwnKk_h6J)
2. To prune, or not to prune: exploring the efficacy of pruning for model compression, Michael H. Zhu, Suyog Gupta, 2017(https://arxiv.org/pdf/1710.01878.pdf)
3. Learning to Prune Filters in Convolutional Neural Networks, Qiangui Huang et. al, 2018(https://arxiv.org/pdf/1801.07365.pdf)
4. Pruning deep neural networks to make them fast and small(https://jacobgil.github.io/deeplearning/pruning-deep-learning)
5. Optimize machine learning models with Tensorflow Model Optimization Toolkit(https://www.tensorflow.org/model_optimization)
星标我,每天多一点智慧