3、结构化剪枝基础:理解结构化剪枝与非结构化剪枝的区别,掌握通道剪枝与滤波器剪枝的原理

各位同学,今天我们来聊聊剪枝。说实话,剪枝这个概念在模型压缩里算是最经典的技术之一了。我最早接触剪枝是在2018年,那时候做移动端部署,模型太大跑不动,硬着头皮啃了几个月剪枝相关的。嗯,踩了不少坑,今天把这些经验分享给你们。

3.1 剪枝到底在干什么?

先问个问题:一个训练好的神经网络,里面所有参数都重要吗?

答案显然是否定的。你想想看,网络里有很多冗余的神经元、通道、甚至整个滤波器,它们对最终结果贡献很小。剪枝就是把这些「摸鱼」的组件去掉,让模型变轻。

我个人习惯把剪枝分成两大类:非结构化剪枝和结构化剪枝。这两者的区别,说白了就是一个「细粒度」一个「粗粒度」。

3.2 非结构化剪枝 vs 结构化剪枝

3.2.1 非结构化剪枝

非结构化剪枝,操作的是单个权重。比如一个卷积核有3×3=9个参数,我们根据某种准则(比如值大小)把其中几个置为0。

核心特点:剪枝粒度是单个参数,稀疏度高,但硬件不友好。

我在项目中遇到过这种情况:用非结构化剪枝把模型压缩了90%,结果在手机上跑,速度一点没变快。为什么?因为稀疏矩阵的加速需要专门的硬件支持,普通CPU/GPU根本吃不到红利。

注意:非结构化剪枝后的模型,如果不配合稀疏计算库(比如TensorRT、OpenBLAS),实际推理速度可能不降反升。我曾经在这个坑里待了两个月。

3.2.2 结构化剪枝

结构化剪枝就不一样了。它剪的是整个结构单元——比如一个通道、一个滤波器、甚至一整层。剪完之后,网络结构变了,但剩下的部分仍然是密集的矩阵运算。

核心特点:剪枝粒度是结构单元,硬件友好,可以直接获得加速效果。

你想想看,剪掉一个通道,意味着卷积层的输入或输出通道数减少了,矩阵乘法规模直接缩小。这在任何硬件上都能加速,不需要特殊支持。

3.3 通道剪枝的原理

通道剪枝,顾名思义,剪的是特征图的通道。具体来说,就是去掉某些通道对应的所有卷积核。

举个例子:假设一个卷积层有64个输出通道,每个输出通道对应一个3×3×C的卷积核。通道剪枝会评估这64个通道的重要性,把不重要的通道连同它对应的卷积核一起删掉。

怎么评估重要性?常见的方法有:

  • 基于权重大小:计算每个通道对应的卷积核权重的L1/L2范数,范数小的认为不重要
  • 基于激活值:统计每个通道输出特征图的均值、方差,激活值小的通道可以剪掉
  • 基于BN层参数:利用Batch Normalization的缩放因子γ,γ接近0的通道可以剪掉

我的经验:在实际项目中,我比较推荐用BN层的γ值来做通道剪枝。原因很简单——不需要额外计算,训练过程中就有了。我曾经在一个分类模型上用这个方法,剪掉40%的通道,精度只掉了0.3%。

3.4 滤波器剪枝的原理

滤波器剪枝和通道剪枝其实是一体两面的。通道剪枝关注的是输出通道,滤波器剪枝关注的是卷积核本身。

每个滤波器(卷积核)对应一个输出通道。所以,剪掉一个滤波器,就等于剪掉一个输出通道。从实现角度看,两者是等价的。

但滤波器剪枝有一个独特的视角:它更关注卷积核内部的结构。比如一个3×3的卷积核,我们可以评估这个核的「能量」——也就是所有参数的平方和。能量低的核,对输出的贡献就小。

滤波器剪枝的典型流程:

  1. 计算每个滤波器的L2范数
  2. 按范数从小到大排序
  3. 设定剪枝比例(比如剪掉30%)
  4. 删除范数最小的那些滤波器
  5. 微调模型恢复精度

我记得有一次做MobileNetV2的剪枝,滤波器剪枝和通道剪枝我都试了。结果发现,对于深度可分离卷积,通道剪枝的效果更好。因为MobileNetV2的逐点卷积(1×1卷积)通道数很多,剪通道的收益更明显。

3.5 结构化剪枝的核心流程图

下面我用一张SVG图来展示结构化剪枝的整体流程,方便大家理解:

结构化剪枝核心流程 预训练模型 原始网络,参数完整 重要性评估 L1/L2范数 / BN-γ 剪枝决策 设定剪枝比例 执行剪枝 删除通道/滤波器 微调恢复精度 少量epoch训练 迭代剪枝 剪枝前后对比 剪枝前: 64个通道 → 计算量大 剪枝后: 32个通道(剪掉50%)→ 速度翻倍 灰色方块表示被剪掉的通道/滤波器

3.6 两种剪枝方式的对比

为了让大家看得更清楚,我整理了一个对比表格:

对比维度 非结构化剪枝 结构化剪枝
剪枝粒度 单个权重/参数 通道、滤波器、层
稀疏模式 不规则稀疏 规则稀疏(结构完整)
硬件加速 需要专用硬件/库 通用硬件直接加速
压缩率 高(可达90%+) 中等(通常30%-60%)
精度损失 较小(可微调恢复) 略大(需要更多微调)
部署难度 高(需稀疏推理引擎) 低(直接导出即可)
典型应用 学术研究、特定加速器 移动端、嵌入式设备

3.7 实际项目中的选择建议

说了这么多,到底该用哪种?我个人的经验是:

  • 做移动端部署,首选结构化剪枝。 因为手机芯片不支持稀疏计算,非结构化剪枝剪了也白剪。
  • 如果目标平台支持稀疏加速(比如某些NPU、TPU),可以尝试非结构化剪枝,压缩率更高。
  • 混合使用效果更好。 我最近的一个项目就是先做结构化剪枝去掉30%的通道,再做非结构化剪枝去掉50%的剩余参数,最终模型大小只有原来的1/4,精度只掉了0.5%。

避坑指南:我曾经在一个项目里,一上来就设了70%的剪枝比例,结果模型直接崩了,精度掉到随机水平。后来学乖了——从小比例开始试,比如10%、20%、30%,每次剪完都评估一下,找到精度下降的拐点。这个拐点就是你的最佳剪枝比例。

3.8 小结

结构化剪枝的核心就两句话:剪结构单元,保硬件效率。通道剪枝和滤波器剪枝本质上是同一件事的不同视角,理解其中一个,另一个自然就懂了。

下一节我们会深入代码层面,手把手实现一个通道剪枝的完整流程。到时候你们会发现,代码实现其实比理论简单得多。


可可精品资料库