直接用torch.quantization.quantize_dynamic做动态量化或用torch.nn.utils.prune做非结构化剪枝,是压缩PyTorch模型体积最快、最稳妥的两条路:前者改数据类型,后者删权重,不需重训练,5分钟内体积可降75%。

直接用 torch.quantization.quantize_dynamic 做动态量化,或用 torch.nn.utils.prune 做非结构化剪枝,是压缩 PyTorch 模型体积最快、最稳妥的两条路。前者改数据类型,后者删权重,不需重训练,5 分钟内就能看到体积下降 75% 的效果。
动态量化:为什么 quantize_dynamic 适合快速部署
它只对 nn.Linear 和 nn.LSTM 这类权重固定、激活值变化大的层做量化,跳过卷积层——这是关键。因为卷积层的激活分布不稳定,动态量化容易引入误差;而全连接层权重本身占模型体积大头(比如 ResNet50 的最后两层),量化后体积直降 4×,且推理时自动转成 int8 计算,显存和速度都受益。
- 必须先调用
model.eval(),否则会报AttributeError: 'TrainEvalHook' object has no attribute 'qconfig' - 只传入要量化的模块类型集合,例如
{torch.nn.Linear},别写成[torch.nn.Linear]或漏掉大括号 - 量化后模型不能继续训练,
quantized_model.train()会出错;如需微调,得回退到量化感知训练(QAT) - 导出时用
torch.jit.script包装后再保存,比直接torch.save更兼容移动端
剪枝:用 prune.l1_unstructured 删权重前必看的三个事实
非结构化剪枝本质是把小权重置零,不改模型结构,所以能直接复用原推理代码。但它生成的是稀疏张量,CPU 上加速有限,GPU 上甚至可能变慢——除非你后续接量化,或者用支持稀疏计算的后端(如 TorchScript + TensorRT)。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
-
amount=0.5表示剪掉 50% 权重,但实际参数量减少 ≠ 体积减少;需配合prune.remove才真正释放内存 - 剪完必须调用
prune.remove(model, 'weight'),否则state_dict里还是满的,保存文件大小几乎不变 - 剪
nn.Conv2d比剪nn.Linear更危险:通道级稀疏易破坏特征图连续性,建议优先剪 FC 层或分类头 - 剪枝后精度掉得快?试试先做 batch norm folding,再剪,能稳住 0.3% 以内精度损失
timm 用户注意:efficientnet_b1_pruned.in1k 这类模型不是“剪完就轻”,而是预设了结构化剪枝策略
它们在加载时已移除整组通道(结构化),不是靠 prune.l1_unstructured 那种零散置零。这意味着你能直接用,但没法再对它做非结构化剪枝——会报 RuntimeError: Can't modify tensor with frozen storage,因为权重已被封装为常量。
立即学习“Python免费学习笔记(深入)”;
- 这类模型的剪枝逻辑藏在
timm/models/efficientnet.py的prune_intermediate_layers函数里,参数如prune_norm=True会影响 BN 层是否参与通道裁剪 - 如果想进一步压缩,只能在其基础上做动态量化,别尝试二次剪枝
- 用
model.named_parameters()查看 weight 形状,若某层输出通道数明显小于原始 EfficientNet-B1(比如从 1280 降到 640),说明结构化剪枝已生效
真正难的不是选量化还是剪枝,而是判断哪部分该量化、哪部分该剪、哪部分干脆该换轻量架构——比如一个带大量 nn.Conv1d 的时序模型,动态量化基本无效,此时应优先考虑结构化剪枝或直接换 MobileNetV3 Backbone。

















