为什么PyTorch的prune剪枝操作没有真正删除权重或滤波器?
问题核心原因说明
你使用的torch.nn.utils.prune系列接口本质是软剪枝,仅做权重数值的掩码置零,不会修改模型的层结构与张量形状:
- 剪枝过程是给原始权重生成一个同尺寸的0/1掩码,运算时掩码和原始权重相乘得到实际生效的权重
- 调用
prune.remove只是把掩码和原始权重的计算结果合并成新的权重张量,张量的形状和原始完全一致,只是其中对应被剪枝的位置数值为0 - 稠密张量的存储规则是不管数值是否为0,每个元素都会占用相同的存储空间,推理时0值也会参与全部矩阵乘法、卷积运算,不会被跳过,因此自然会出现参数总量不变、模型文件大小不变、推理速度无提升的情况,该现象和你用非结构化剪枝、全局剪枝、结构化L1剪枝的选型无关,只要没有修改模型结构结果都是一致的。
剪枝实现实际性能提升的前提
剪枝要拿到真实的速度、体积收益,需要满足两个条件之一:
- 对于非结构化剪枝(零散置零单个权重):需要部署在支持稀疏张量运算的硬件(如NVIDIA A100/A10的稀疏张量核),或者使用支持稀疏推理的引擎(如开启稀疏特性的TensorRT、ONNX Runtime),才能跳过0值运算拿到收益,普通硬件和通用推理框架无法利用非结构化的稀疏性
- 对于结构化剪枝(按通道、头、模块粒度剪枝):需要真正把被剪掉的结构从模型中删除,修改对应层的输入输出维度,普通硬件就能直接拿到线性的性能提升,这也是目前工业界最常用的剪枝落地方案
如何真正移除被剪枝的连接
结构化剪枝(推荐通用场景使用)
结构化剪枝后需要手动/工具自动修改模型的层结构,以卷积层通道剪枝为例:
- 剪枝时统计每个卷积输出通道的权重指标(如L1和、激活值稀疏度等),确定需要保留的通道索引
- 替换当前卷积层为新的卷积层,输出通道数调整为保留的通道数量,权重赋值为原始权重对应保留通道的切片,偏置同步切片
- 同步修改下一层算子的输入通道数,下一层权重的输入维度也按相同的保留索引切片,保证张量维度匹配
- 结构修改完成后,可以做少量微调恢复精度,此时导出的模型参数总量、体积、推理速度都会对应下降
可以使用开源工具简化操作,如TorchPrune、NNI剪枝工具链,都自带剪枝后结构自动转换的能力,无需手动修改每层维度。
非结构化剪枝(仅适合支持稀疏运算的场景)
如果要使用非结构化剪枝的收益,操作如下:
- 剪枝完成后将所有权重张量转换为PyTorch稀疏张量格式,减少存储占用
- 导出模型时转换为对应推理框架支持的稀疏格式,部署时开启推理引擎的稀疏运算开关,即可跳过0值运算提升速度
内容的提问来源于stack exchange,提问作者Anvar Ganiev
相关产品推荐
相关产品推荐

