模型剪枝基础:结构化剪枝与非结构化剪枝原理、粒度与稀疏性

模型剪枝,说白了就是给神经网络“瘦身”。

我刚开始接触这个领域时,总觉得剪枝就是把权重砍掉一些,没什么技术含量。直到我在一个边缘AI项目里,要把一个ResNet-50塞进只有2MB SRAM的芯片里,才发现——剪枝的门道深着呢。

今天咱们就聊聊剪枝的两个核心流派:结构化剪枝和非结构化剪枝。以及它们背后的粒度与稀疏性概念。

一、剪枝的本质:砍掉冗余连接

神经网络里,很多权重其实接近于零。这些权重对最终结果贡献极小,砍掉它们,模型精度几乎不受影响。

为什么会这样?因为训练过程中,某些神经元或连接被“学废了”——它们要么输出恒定,要么权重极小。保留它们,只是浪费计算资源和存储空间。

核心思想:在保持模型精度的前提下,移除不重要的参数,从而减少计算量、降低存储需求、加速推理。

我习惯把剪枝分为两个维度:

  • 按结构分:结构化剪枝 vs 非结构化剪枝
  • 按粒度分:细粒度剪枝、向量级剪枝、核级剪枝、通道级剪枝、层级剪枝

这两个维度交叉组合,就构成了剪枝的完整技术图谱。

二、非结构化剪枝:精细但“难伺候”

非结构化剪枝,也叫细粒度剪枝。它直接对单个权重做判断——权重绝对值小于某个阈值,就把它置零。

举个例子:

# 非结构化剪枝示例(PyTorch风格)
import torch
import torch.nn.utils.prune as prune

model = torch.nn.Linear(10, 5)
# 对权重进行L1范数剪枝,保留30%的权重
prune.l1_unstructured(model, name='weight', amount=0.7)

# 查看剪枝后的权重
print(model.weight)
# 输出中很多权重变成了0.0

你看,代码很简单。但实际项目中,我踩过一个大坑——非结构化剪枝后的模型,在普通硬件上几乎跑不快

避坑指南:我曾经在一个FPGA部署项目里,对卷积层做了50%的非结构化剪枝。结果呢?推理速度几乎没变。因为FPGA的乘加器是并行计算的,零权重并不会跳过计算——它依然占用一个乘法器周期。

非结构化剪枝的优点是精度损失小。因为它保留了模型原有的拓扑结构,只是把某些权重置零。但缺点也很明显:

  • 权重矩阵变成稀疏矩阵,需要专门的稀疏计算库(如cuSPARSE)才能加速
  • 对硬件不友好,通用处理器(CPU/GPU)很难利用这种稀疏性
  • 模型文件大小可能不变(因为零值依然占用存储空间)

所以,非结构化剪枝更适合学术研究,或者你有专门的稀疏计算硬件。否则,我建议你慎重。

三、结构化剪枝:粗暴但实用

结构化剪枝,是直接砍掉整个结构单元——比如一个通道、一个卷积核、甚至一整层。

你想想看,如果某个卷积核的所有权重都很小,那这个卷积核基本就是废的。直接删掉它,模型结构就变小了。

举个例子:

# 结构化剪枝示例:按通道剪枝
# 假设我们有一个Conv2d层,输入通道64,输出通道128
# 我们对输出通道做剪枝,保留最重要的64个通道

import torch
import torch.nn as nn

# 计算每个通道的L2范数作为重要性指标
conv = nn.Conv2d(64, 128, kernel_size=3)
importance = torch.norm(conv.weight.view(128, -1), dim=1)  # 每个输出通道的L2范数

# 保留前64个最重要的通道
_, indices = torch.topk(importance, 64)
# 然后根据indices重新构建一个更小的卷积层

结构化剪枝的好处是:

  • 直接减少计算量——通道数减半,计算量也减半
  • 硬件友好——剪枝后的模型依然是密集矩阵,通用硬件可以直接加速
  • 模型体积缩小——参数数量实实在在减少了

但代价是精度损失更大。因为一刀切地砍掉整个通道,可能会误伤一些有用的特征。

我的经验:在实际项目中,我通常先用结构化剪枝把模型压缩到目标大小的80%,然后用知识蒸馏或微调来恢复精度。这样既保证了推理速度,又不会让精度掉得太难看。

四、粒度与稀疏性:剪枝的“精细度”

剪枝的粒度,决定了你砍掉的是“多大一块”。

粒度级别 描述 稀疏性类型 硬件友好度
细粒度(权重级) 单个权重置零 非结构化稀疏
向量级 连续N个权重一起置零 半结构化稀疏
核级 整个卷积核置零 结构化稀疏
通道级 整个通道置零 结构化稀疏
层级 整层删除 结构化稀疏 最高

稀疏性,就是模型中零值参数的比例。比如一个模型有100万个参数,其中30万个是零,那稀疏度就是30%。

但要注意:稀疏度不等于加速比。非结构化剪枝达到90%稀疏度,在普通GPU上可能只加速1.2倍。而结构化剪枝达到50%稀疏度,加速比可能直接翻倍。

为什么会这样?因为硬件对“规则”的稀疏性更友好。你想想看,如果零值分布是随机的,硬件没法做批量跳过。但如果零值是以通道为单位的,硬件可以直接跳过整个通道的计算。

五、如何选择?我的建议

在实际项目中,我一般遵循这个原则:

  1. 目标硬件是GPU/CPU:优先用结构化剪枝。因为GPU的Tensor Core对密集矩阵优化得最好。
  2. 目标硬件是专用AI芯片:看芯片是否支持稀疏计算。如果支持,可以尝试非结构化剪枝+稀疏加速。
  3. 精度要求极高:先用非结构化剪枝做探索,找到精度-稀疏度的边界,再转为结构化剪枝。
  4. 模型太大,内存装不下:必须用结构化剪枝。因为非结构化剪枝不减少模型的内存占用(零值依然占位)。

一句话总结:结构化剪枝保速度,非结构化剪枝保精度。实际项目中,我通常两者结合——先用结构化剪枝砍到目标大小,再用非结构化剪枝微调恢复精度。

六、知识体系图

下面这张图,帮你理清剪枝的核心逻辑:

模型剪枝知识体系 模型剪枝 非结构化剪枝 结构化剪枝 权重级剪枝 向量级剪枝 核级剪枝 通道级剪枝 层级剪枝 组级剪枝 特性对比 精度损失: 非结构化 < 结构化 加速效果: 结构化 > 非结构化 硬件友好: 结构化 > 非结构化 实现难度: 非结构化 < 结构化

嗯,这张图把剪枝的脉络理得很清楚。左边是非结构化路线,右边是结构化路线。底部是它们的核心差异对比。

我个人习惯在项目初期,先用非结构化剪枝做个快速评估——看看模型在多大稀疏度下还能保持精度。然后根据目标硬件,选择合适的结构化剪枝策略。

记住一点:剪枝不是目的,部署才是。你剪得再漂亮,如果硬件跑不快,那就是白费功夫。

小技巧:如果你不确定该用哪种剪枝,先问自己三个问题:

  1. 我的目标硬件支持稀疏计算吗?
  2. 我的模型精度余量有多大?
  3. 我的部署时间窗口有多紧?

答案自然就有了。


公众号:蓝海资料掘金营,微信deep3321