本节为分为两个部分:
- 剪枝的原理和技术
- 机器硬件对剪枝的支持
Section 1 剪枝技术以及原理
1. 剪枝的介绍
一个形式化的对剪枝的介绍:
说人话就是,寻找一个最优的 Wp ,在保证 零权重(值为零的权重)的个数 小于一个阈值(N)的时候,使得 目标函数 的值最小。
为了正确应用剪枝,需要回答以下的问题:
- 怎么剪:选择哪些权重进行剪枝
- 剪什么:选择权重的哪些部分进行剪枝
- 剪多少:选择剪多少比例的权重?
2. 剪枝的粒度(怎么剪)
一张图完美概括,从左往右,剪枝的粒度越来越大(即越来越粗糙)。
粒度越小,选择越灵活,模型的效果越好;
粒度越大,选择越不灵活,但是更适合计算。
在第一种选择下,还可以选择剪枝神经元还是剪枝突触。
在第二种选择下,有一种特殊的 N:M的剪枝方法。这里以2:4为例子。
在最后一种选择下,可以直接剪枝掉整个通道。
2. 剪枝的策略(剪什么)
第一个方法相当直观,如果一个权重很小的话,那么他就是不重要的,所以可以被剪枝掉。
当然,顺着这个思路可以继续拓展。
也可以选择不同的函数作为标准:
第二个方法是基于让机器自己学习应该剪枝哪些权重,具体方法是学习一个缩放因子,然后在模型收敛时剪枝掉那些小因子所在的权重。(这个因子可以直接复用BatchNorm的因子)
第三个方法是基于激活值的。ReLU函数会创造大量的0值,如果一个层输出过多的0,那么这个层相对来说并不重要,即可以被剪枝。
第四个方法是基于回归的,说人话就是选择一个 影响输出最小的 权重进行剪枝。
3. 剪枝的比例(剪多少)
一般来说,非均匀的剪枝会比均匀的剪枝更好。
第一个方法是观察神经网络每层的 敏感性。即对每一层进行剪枝实验,观察他们对输出的影响。(这里假设所有的层之间都是相互独立的)。如图,L0对剪枝更敏感因为在剪掉70%左右之后精度明显下降,而L1则不敏感因为在剪掉90%后,精度也没有掉很多。所以一个好的方式是直接设置一个阈值(T),让机器自动决定剪枝的比例。
第二个方法是自动剪枝,通过设置奖励函数,用强化学习的方式让机器自动完成剪枝。
第三个方法叫NetAdapt。它的原理是,先人为设置一个全局限制(如延迟或FLOPS),接着让机器设置剪枝比例以满足限制。接着对整个网络进行小的微调,再选出精度最高的层进行剪枝。重复这个过程,最后就能得到剪枝好的模型。
4. 微调与训练
剪枝的过程是迭代进行的,即:
- 先剪枝30%,再微调
- 再剪枝50%,再微调
- 再剪枝70%,再微调
- …
超参数设置中,一般最关心的是学习率(初始训练学习率的 0.1 或 0.01)以及weight decay。