第4章:模型剪枝理论基础
剪枝这玩意儿,说白了就是给神经网络「瘦身」。我刚开始接触剪枝时,总觉得这跟直接砍掉模型参数没啥区别。后来踩了不少坑才明白——剪枝不是简单粗暴地删东西,而是有策略地做取舍。
这一章,咱们把剪枝的理论基础掰开揉碎。你理解透了,后面实操才不会走弯路。
4.1 剪枝的分类:结构化 vs 非结构化
先问个问题:剪枝到底剪什么?
答案很简单——剪掉那些「不重要」的参数。但怎么定义「不重要」,就分出了两大流派。
4.1.1 非结构化剪枝
非结构化剪枝,也叫细粒度剪枝。它直接干掉单个权重或神经元连接。
举个例子:一个卷积核是 3×3 的矩阵,里面有些权重值特别小。非结构化剪枝就把这些值直接置零。
优点很明显——剪枝率高,模型压缩比大。我曾在某个分类任务上,把 80% 的权重都剪掉了,精度只掉了 0.5%。
但缺点也很致命——权重矩阵变得稀疏了。稀疏矩阵在普通硬件上跑,速度反而更慢。你得用专门的稀疏计算库,比如 NVIDIA 的 cuSPARSE。说白了,就是「剪得爽,跑得慢」。
4.1.2 结构化剪枝
结构化剪枝就聪明多了。它不剪单个权重,而是剪整个「结构单元」——比如一个通道、一个卷积核、甚至一整层。
这样做的好处是:剪完之后,模型结构还是规整的。你不需要特殊硬件,直接跑在普通 GPU 上就能加速。
我在项目中遇到过一件事:用非结构化剪枝剪了个 YOLOv5,精度还行,但推理速度没变。换成结构化剪枝后,模型小了 40%,速度提升了 1.5 倍。嗯,从那以后,工业项目我首选结构化剪枝。
| 类型 | 剪枝粒度 | 硬件友好度 | 压缩比 | 典型场景 |
|---|---|---|---|---|
| 非结构化 | 单个权重 | 低 | 高 | 学术研究 |
| 结构化 | 通道/卷积核/层 | 高 | 中 | 工业部署 |
4.2 剪枝粒度:从权重到层
剪枝粒度,就是「你一次剪多大一块」。我习惯把它分成三个级别。
4.2.1 权重级剪枝
这是最细的粒度。每个权重独立判断是否保留。
判断标准很简单:看权重的绝对值大小。绝对值越小,说明它对输出的贡献越小,剪掉它影响不大。
你想想看,一个权重值只有 0.001,跟一个权重值 0.5 的比,谁更重要?显然是后者。
4.2.2 通道级剪枝
这是工业界最常用的粒度。剪掉整个通道,相当于删掉了一整个特征图。
怎么判断一个通道重不重要?看它的 L1 范数。把所有权重的绝对值加起来,和越小,说明这个通道越「懒」。
我曾经剪过一个 YOLOv5s 模型,把 30% 的通道都砍了。结果呢?模型大小从 14MB 降到 8MB,mAP 只掉了 1.2%。这个性价比,我觉得很值。
4.2.3 层级剪枝
层级剪枝最暴力——直接删掉一整层。比如 ResNet 里的某个残差块,或者 YOLO 里的某个 C3 模块。
什么时候用?模型特别深,或者某些层确实「没用」的时候。我见过一个极端案例:某个检测模型有 100 多层,剪掉最后 10 层后,精度几乎没变。说白了,那些层就是在「摸鱼」。
4.3 剪枝评价指标
剪得好不好,不能光看模型大小。你得有「尺子」去量。我常用的指标有这几个。
4.3.1 精度损失
这是最直接的指标。剪枝前后的精度对比。
公式很简单:
精度损失 = 原始精度 - 剪枝后精度
一般来说,精度损失控制在 1% 以内,算优秀。1%-3%,可以接受。超过 3%,你得重新调剪枝策略了。
4.3.2 压缩比
压缩比 = 原始模型大小 / 剪枝后模型大小
比如原始模型 100MB,剪完后 50MB,压缩比就是 2x。
但要注意:压缩比高不代表推理速度快。非结构化剪枝压缩比能做到 10x,但推理速度可能只提升 1.2x。结构化剪枝压缩比 2x,推理速度可能提升 2x。
4.3.3 加速比
这才是工业界最关心的指标。
加速比 = 原始推理时间 / 剪枝后推理时间
我曾经做过一个对比:同样剪掉 50% 的参数,非结构化剪枝加速比只有 1.1x,结构化剪枝加速比达到了 1.8x。为什么?因为结构化剪枝减少了计算量,而不仅仅是参数量。
| 指标 | 含义 | 理想值 | 注意点 |
|---|---|---|---|
| 精度损失 | 剪枝前后精度差 | < 1% | 分类任务看 Top-1,检测任务看 mAP |
| 压缩比 | 模型大小缩减倍数 | 2x - 5x | 非结构化压缩比高但加速有限 |
| 加速比 | 推理速度提升倍数 | 1.5x - 3x | 结构化剪枝加速效果更好 |
| FLOPs 减少率 | 计算量减少比例 | 30% - 60% | 与加速比正相关 |
4.3.4 FLOPs 减少率
FLOPs 是浮点运算次数。减少 FLOPs,就是减少计算量。
这个指标跟加速比强相关。一般来说,FLOPs 减少 50%,加速比能到 1.8x 左右。
但要注意:FLOPs 减少率 ≠ 加速比。因为还有内存访问、数据搬运等开销。我见过一个模型,FLOPs 减少了 60%,但加速比只有 1.5x。原因就是内存带宽成了瓶颈。
4.4 避坑指南
最后分享几个我踩过的坑。
坑一:剪枝后不重训练。 我曾经以为剪完直接部署就行,结果精度掉了 5%。后来老老实实做重训练,精度才回来。记住:剪枝只是第一步,重训练才是关键。
坑二:只看压缩比不看加速比。 有个项目,我剪到了 5x 压缩比,但推理速度只快了 10%。后来换成结构化剪枝,压缩比 2x,加速比到了 2x。嗯,从此我学会了「以加速比为导向」。
坑三:一次性剪太多。 我刚开始做剪枝时,总想一步到位。结果剪完模型直接崩了。后来改成「迭代剪枝」——每次剪 10%,重训练,再剪 10%。这样稳多了。
好了,这一章的内容就到这里。剪枝的理论基础,说白了就是「怎么剪」和「怎么评价」。下一章,咱们会讲具体的剪枝算法,比如 L1 范数剪枝、BN 层剪枝。到时候,我会带着代码一步步演示。
记住:理论是基础,实践出真知。别光看,动手试试。