剪枝理论基础:从“胖模型”到“瘦身达人”的必修课
大家好,我是你们的老朋友。今天咱们聊聊剪枝的理论基础。
说实话,我刚入行那会儿,觉得剪枝就是“把不重要的权重砍掉”。后来踩了不少坑才发现——剪枝不是简单的“砍”,而是一门关于“怎么砍、砍多少、什么时候砍”的系统工程。
这一章,我会把剪枝的分类、粒度、标准这三个核心问题掰开揉碎讲清楚。你想想看,搞懂了这些,后面实战才不会手忙脚乱。
核心观点:剪枝的本质是在精度和效率之间找平衡。没有“最好”的剪枝方法,只有“最适合你场景”的方法。
一、剪枝的分类:先搞清楚你在哪条赛道上
剪枝的分类,说白了就两个维度:结构化和非结构化,以及静态和动态。
1.1 结构化 vs 非结构化剪枝
这是最基础也是最重要的分类。我习惯这么理解:
- 非结构化剪枝:像“点穴”,只干掉单个权重。灵活度高,但硬件不买账。
- 结构化剪枝:像“切块”,直接干掉整个通道或层。硬件友好,但精度损失可能更大。
我在项目中遇到过这样一个场景:用非结构化剪枝把模型压缩了90%,结果在GPU上跑,速度一点没变。为什么?因为稀疏矩阵的运算,硬件根本加速不了。后来换成结构化剪枝,虽然压缩率只有60%,但推理速度直接翻倍。
我的建议:如果你用GPU推理,优先考虑结构化剪枝。如果是CPU或者专用芯片,非结构化剪枝可能更香。
1.2 静态 vs 动态剪枝
这个分类很多人容易搞混。我简单解释一下:
- 静态剪枝:训练完再剪,剪完就固定了。简单粗暴,适合部署。
- 动态剪枝:推理时根据输入动态决定剪哪些。更灵活,但实现复杂。
嗯,这里要注意:动态剪枝虽然效果好,但工程实现难度大。我曾经在一个实时性要求很高的项目里尝试动态剪枝,结果剪枝本身的耗时比推理还长……后来老老实实用了静态剪枝。
二、剪枝粒度:从“细胞”到“器官”的四个层次
剪枝粒度,就是你要“砍”的最小单位。我把它分成四个层次:
| 粒度 | 描述 | 硬件友好度 | 精度保留度 |
|---|---|---|---|
| 细粒度 | 单个权重 | 低 | 高 |
| 向量粒度 | 一行或一列权重 | 中 | 中 |
| 通道粒度 | 整个卷积核或全连接层的一整列 | 高 | 中低 |
| 层粒度 | 整个网络层 | 最高 | 低 |
你想想看,细粒度剪枝就像“精准打击”,精度保留最好,但硬件不支持。通道粒度是“区域轰炸”,硬件跑得飞快,但精度可能掉得厉害。
我个人习惯是:先用通道粒度剪掉明显不重要的通道,再用细粒度微调。这样既保证了速度,又尽量保住了精度。
避坑指南:我曾经在一个BERT模型上直接做层粒度剪枝,一口气砍掉了4层。结果模型直接“失忆”,下游任务精度掉了15个点。后来我才明白——层粒度剪枝只适合那些有冗余结构的模型(比如ResNet的残差块),别乱用。
三、剪枝标准:凭什么决定“砍谁”?
这是剪枝的核心问题。我常用的标准有三种:
3.1 权重幅度(Magnitude)
最简单也最常用。说白了就是:谁的绝对值小,谁就不重要。
# 伪代码示例
def magnitude_pruning(weights, sparsity):
threshold = np.percentile(np.abs(weights), sparsity * 100)
mask = np.abs(weights) > threshold
return weights * mask
这个方法我用了很多年。优点是快,缺点是太“天真”——它假设所有层的重要性是一样的。实际上,浅层的权重即使很小,也可能很重要。
3.2 梯度(Gradient)
梯度反映了权重对损失的影响。如果某个权重的梯度一直很小,说明它“可有可无”。
我记得有一次做图像分类模型剪枝,用幅度剪枝剪到80%稀疏度时,精度掉了5个点。换成梯度剪枝后,同样的稀疏度只掉了2个点。为什么?因为有些权重虽然绝对值大,但对最终结果影响不大。
小技巧:可以把幅度和梯度结合起来,比如用 |weight| * |gradient| 作为重要性指标。我在多个项目里试过,效果比单独用任何一个都好。
3.3 海森矩阵(Hessian)
这是最“高级”的方法。海森矩阵衡量的是损失函数对权重的二阶导数。说白了就是:这个权重变化了,损失会怎么变?
用海森矩阵剪枝,精度保留最好,但计算代价巨大。一个百万参数的模型,海森矩阵就有万亿个元素。所以实际中很少直接用,而是用近似方法(比如OBD、OBS算法)。
嗯,这里要提醒一下:海森矩阵方法虽然理论优美,但工程实现非常复杂。我建议初学者先别碰,等把幅度和梯度玩熟了再说。
四、知识体系总览
为了让你更直观地理解本章的知识结构,我画了一张图:
这张图把本章的核心内容串起来了。你仔细看看,会发现三个维度其实是相互影响的——比如你选了结构化剪枝,那粒度大概率就是通道或层级别;你选了海森矩阵标准,那计算量就会很大。
五、实战中的选择策略
说了这么多理论,最后给点实用的。我总结了一个选择策略:
- 先看硬件:如果是GPU,选结构化+通道粒度;如果是CPU,可以试试非结构化+细粒度。
- 再看精度要求:精度要求高,用梯度或海森矩阵标准;要求不高,幅度标准就够了。
- 最后看时间:时间紧,用静态剪枝;时间充裕,可以试试动态剪枝。
我的经验:80%的场景下,用“幅度标准 + 通道粒度 + 静态剪枝”就能拿到不错的结果。别一上来就追求最复杂的方法,先跑通一个基线再说。
好了,这一章的内容就到这里。剪枝的理论基础,说白了就是搞清楚“砍什么、怎么砍、凭什么砍”。下一章我们会深入具体的剪枝算法,到时候再聊。
公众号:蓝海资料掘金营,微信deep3321