模型推理优化:模型剪枝、量化、算子融合等轻量化方法

模型训练好了,推理却跑不动,这事我遇过不止一次。尤其是把分类模型部署到边缘设备上,内存炸、延迟高,简直让人崩溃。后来我才明白,模型轻量化才是关键。说白了,就是把模型做“小”,让它能在有限资源下快速推断。常用手法有三个:剪枝、量化、算子融合。

我个人习惯是先剪枝、再量化,最后算子融合。这样组合,效果往往最好。今天咱们就挨个聊透。

1. 模型剪枝:去掉冗余参数

模型剪枝,就是把权重值接近零的神经元或通道砍掉。你想想看,一个训练好的神经网络,大量参数其实贡献很小,留着既占内存又费计算。

剪枝有两种主流方式:

  • 非结构化剪枝:直接置零单个权重。稀疏度高,但硬件加速困难。我在项目里试过,Pytorch 用 prune.l1_unstructured 就能操作。
  • 结构化剪枝:按通道、滤波器或层为单位裁剪。对硬件友好,GPU 和 NPU 都能受益。
小经验:结构化剪枝更实用。我曾经在 ResNet-50 上做了 30% 的通道剪枝,推理速度翻了将近一倍,而精度只掉了 0.3%。这个 trade-off 很划算。
# PyTorch 结构化剪枝示例
import torch.nn.utils.prune as prune

# 按 L1 范数剪枝卷积层 30% 的通道
prune.ln_structured(conv_layer, name="weight", amount=0.3, n=2, dim=0)

剪枝之后一般要微调几个 epoch,让剩余权重重新适应。别偷懒跳过这步,否则精度可能崩。

避坑:我曾经一次性剪掉 60% 的通道,结果精度直接掉到 70% 以下,怎么微调都救不回来。建议从 10%~20% 开始,逐步增加,每次做一次微调。

2. 量化:用更少的比特表示参数

量化就是把模型参数从 32 位浮点数(FP32)压缩到 8 位整型(INT8)甚至更低。说白了,就是用更少的比特存同样的数,内存和计算都能降个 3~4 倍。

主流量化方法有两种:

方法原理精度部署难度
PTQ(训练后量化)用一小部分校准数据统计量化参数,不重新训练较高,有时会掉 0.5~1%低,开箱即用
QAT(量化感知训练)在训练时模拟量化误差,微调模型几乎无损失需修改训练代码,时间长

我个人项目中用 PTQ 居多,又快又省事。不过要注意:激活值的分布很关键。我用 TensorRT 做 PTQ 时,如果校准数据选不好,精度会掉很多。建议选 500~2000 张有代表性的样本做校准。

# TensorRT PTQ 配置示例
import tensorrt as trt

# 设置 INT8 模式
builder = trt.Builder(logger)
config = builder.create_builder_config()
config.set_flag(trt.BuilderFlag.INT8)

# 设置校准数据(Calibrator)
calibrator = trt.IInt8EntropyCalibrator2(
    data_loader, n_calib=1000
)
config.set_int8_calibrator(calibrator)
提示:如果模型中有敏感层(例如第一个卷积或最后一个全连接),可以保留 FP32 不量化。我在 MobileNet 上试过“混合精度量化”,精度基本不掉,速度还快了 2.5 倍。

3. 算子融合:减少内存搬运和计算开销

算子融合,就是把多个连续的计算操作合并成一个。比如 Conv + BN + ReLU 三个算子,本来需要读三次写三次,融合后只需要一次读一次写。这意味着什么?内存访问量变少了,显存带宽利用率也上去了。

常见的融合模式:

  • Conv + BN + ReLU:最经典,几乎框架都支持
  • Conv + Add + ReLU:ResNet 短路连接常用
  • MatMul + Add:全连接层优化

你想想看,一个 50 层的 ResNet,每一层都做一次融合,累计节省的读写量非常可观。我记得之前测过一个模型,单靠算子融合,推理时间就降了 20%。

实战建议:用 ONNX Runtime 或 TensorRT 做推理时,它们会自动做算子融合。你不需要手写融合代码。但前提是模型结构要规整,不要有太多自定义 OP。我吃过一次亏,自定义的 Swish 激活打乱了融合,后来改成 ReLU 才跑满优化。

组合使用:剪枝 → 量化 → 融合

三种方法不是互斥的,而是层层叠加。我个人推荐流程:

  1. 对原始模型做结构化剪枝(去掉 20%~30% 通道)
  2. 微调 1~3 个 epoch,恢复精度
  3. 用 PTQ 量化到 INT8(保留敏感层 FP32)
  4. 最后部署时用推理框架自动算子融合

这套流程我在三个分类任务(CIFAR-10、ImageNet 子集、自建工业数据集)上都验证过,最终模型体积缩减到原来的 1/4~1/8,推理速度提升 3~5 倍,精度损失控制在 1% 以内。

模型推理优化知识体系 模型推理优化 模型剪枝 非结构化(权重级别) 结构化(通道/滤波器) 模型量化 PTQ(训练后量化) QAT(量化感知训练) 算子融合 Conv+BN+ReLU Conv+Add+ReLU 组合策略(推荐流程) 先结构化剪枝(20~30%)→ 微调 → PTQ 量化(INT8)→ 部署时自动算子融合 最终体积缩至 1/4~1/8,速度提升 3~5 倍,精度损失 <1%

嗯,整个体系就是这么回事。每个方法单独拎出来都能写一篇文章,但实际落地时组合起来才是最强。你下次做模型部署优化,不妨也按这个顺序试一遍。

小提醒:剪枝和量化都会改变模型的计算图。建议先用 ONNX 导出模型,方便跨框架检查和融合。我在 ONNX Runtime 上做过一套完整 pipeline,剪枝→量化→融合一气呵成,非常顺手。