模型剪枝算法综述笔记
今天把最近看的一批模型剪枝相关论文整理了一下,方法大体可以分为三类:预定义结构剪枝、自动结构剪枝和非结构化剪枝。
先提一篇引发思考的文章:它做了大量对比实验,结论是——如果剪枝后的网络结构是预先定义好的,那么直接从头(scratch)训练这个瘦网络就能得到比较好的结果,没有必要再走那套繁琐的”预训练 → 剪枝 → fine-tune”流程。实验覆盖了 Predefined Structured Pruning、Automatic Structured Pruning、Unstructured Magnitude-based Pruning 三个方向。
预定义结构化剪枝
这类方法的共同点是:在执行剪枝之前,先由人工或通过敏感性分析确定每一层要删掉多少比例的 filter/channel,算法只负责在给定比例内找”最不重要”的那些。
L1 剪枝
论文:Pruning Filters for Efficient ConvNets
最直接的做法:把 L1 范数最小的卷积核直接去掉,相当于砍掉下一层的 channel 数。每层的剪枝比例是固定的,依赖事先做好的敏感性分析——逐层单独剪枝,在验证集上测精度;再对剪后的单层重新训练,再测精度,由此确定每层对剪枝的容忍度。如果没有预训练模型,这套流程意义不大,还不如重新训练。
ThiNet
论文:ThiNet: A Filter Level Pruning Method for Deep Neural Network Compression
目标是:剪掉第 L 层的若干 filter 后,尽量保持第 L+2 层的输入(即第 L+1 层的输出)不变。删掉 L 层的 filter 后,L+1 层对应的输入 channel 数和 filter channel 数也随之减小。
做法是用贪心算法在第 L+1 层的输出里找对整体影响最小的 channel——按 feature map 维度和 batch 维度上绝对值之和排序,逐步去掉影响最小的那个。需要优化的式子如下(m 是分辨率 × channel 数 × batch 大小):
使用的贪心算法如下:
LASSO 回归剪枝
论文:Channel Pruning for Accelerating Very Deep Neural Networks
出发点和 ThiNet 类似,同样是希望剪掉某些 channel 后让下游层响应尽量不变,但用 LASSO 回归的稀疏正则项替代了贪心搜索。对每个 channel 引入加权系数 β,目标是让 β 尽可能稀疏,同时保持重建误差最小。N 是采样的卷积输入块数量,Y 是 N×n 的特征矩阵:
求解采用交替优化,分两步:
Step 1:固定 w,优化 β,直接当作 LASSO 回归问题求解:
Step 2:固定 β,优化 w:
与 ThiNet 的主要区别就在求解算法上,这里是交替优化而不是贪心枚举。
自动结构化剪枝
这类方法不需要人工指定每层的剪枝比例,训练过程本身会决定哪些 channel 该去掉,某种程度上可以看作轻量级的 NAS。
Network Slimming
论文:Learning Efficient Convolutional Networks through Network Slimming
在 BN 层的缩放参数(γ)上加 L1 正则化。由于 BN 层的 weight 是在 channel 维度上独立作用的,某个 channel 对应的 γ 趋近于零就意味着这个 channel 的输出几乎被压制,可以直接剪掉。
与 L1 filter pruning 的关键区别:Network Slimming 的阈值是对所有 BN 层的 γ 做全局排序后得出的,而 L1 剪枝是在每层内部做相对排序。前者不需要人工指定每层的压缩比,结构自动涌现。L1 不可导,实现时直接对梯度做操作(次梯度),用普通 SGD 即可收敛。
Sparse Structure Selection
论文:Data-Driven Sparse Structure Selection for Deep Neural Networks
思路与 Network Slimming 类似,通过数据驱动的稀疏正则化让网络自动选择结构。
其他值得关注的方法
AOFP(ICML 2019)
论文:Approximated Oracle Filter Pruning for Destructive CNN Width Optimization
用二分搜索来定位最不重要的 channel,通过多次随机采样估计每个 channel 对下一层输出的影响,然后剪掉影响较小的 channel。用采样来近似估计影响量,避免枚举所有组合,这个思路挺值得借鉴的。
NISP
论文:NISP: Pruning Networks Using Neuron Importance Score Propagation
同样是预定义每层剪枝比例,再按某种重要性分数进行剪枝,属于预定义类方法的变体。
SNIP
论文:SNIP: Single-Shot Network Pruning Based on Connection Sensitivity
非结构化剪枝,直接剪掉 loss 对 mask 梯度最小的连接——即对 loss 最不敏感的 weight。其中 s 是敏感度,用近似微分来得到:
这样只需一次 backward 就能算出所有 weight 的敏感度,不需要多次 forward:
Autopruner
论文:Autopruner: An End-to-End Trainable Filter Pruning Method for Efficient Deep Model Inference
不用简单的惩罚项来驱动稀疏,而是用额外的网络结构来预测每个 filter 的 mask。对 sigmoid 做了改造,逐渐增大 α 使激活值越来越接近 0/1 编码,相当于用神经网络激活值直接充当 mask,这样可以端到端用反向传播找到最佳编码。缺点是压缩率不易控制,还需要额外措施。
激活函数形式如下:
压缩率的控制通过在 loss 中加正则项实现,v 是编码向量,C 是向量长度,r 是目标保留比例:
其他备忘
- ISTA-based(Rethinking the Smaller-Norm-Less-Informative Assumption in Channel Pruning of Convolution Layers):暂跳过,看着很费劲,之后再补。
- C-SGD(Centripetal SGD for Pruning Very Deep Convolutional Networks with Complicated Structure):针对 ResNet 这类有复杂跳接结构的网络设计。
- AMC(AMC: AutoML for Model Compression and Acceleration on Mobile Devices):用 DDPG 搜索每层的压缩比超参,把确定”剪多少”这件事也交给强化学习来解决。
- SFP(Soft Filter Pruning for Accelerating Deep Convolutional Neural Networks)、CFP、GDP、SSR-L2、DCP 等:记下来,后续有时间细读。
- Influence Functions(Understanding Black-Box Predictions via Influence Functions):好像也是利用求导找敏感度,和 SNIP 的思路有相通之处。
小结
结构化剪枝(无论预定义还是自动)在硬件加速上更友好,能直接缩小网络规模;非结构化剪枝虽然理论压缩比更高,但稀疏矩阵在常规 GPU 上难以真正加速,实用价值有限。自动结构剪枝和 NAS 越来越接近,Network Slimming 用稀疏正则、AMC 用强化学习,分别代表两种搜索结构的路线,是目前看来比较有意思的方向。
另外,今天还看了 MixMatch 的论文,把 CSAPP 第三章看完了,收获不少。