第二章:模型部署基础
2.1 模型部署流程概览
模型部署这件事,说白了就是把训练好的模型搬到生产环境里跑起来。我见过不少团队,模型在GPU上跑得飞快,一上手机或者边缘设备就卡成PPT。为什么会这样?因为部署不是简单的「复制粘贴」。
我个人习惯把部署流程拆成四个阶段:
- 模型导出:把PyTorch/TensorFlow的模型转成中间格式
- 格式转换:针对目标硬件做优化(比如转成TensorRT)
- 量化压缩:把FP32变成INT8,体积变小速度变快
- 运行时优化:内存管理、流水线调度这些工程细节
嗯,这里要注意:每个阶段都可能踩坑。我在项目中遇到过最典型的问题——模型导出时一个算子不支持,结果整个流程卡了两天。所以我的建议是:先跑通最小闭环,再逐步优化。
核心原则:部署不是训练的终点,而是工程化的起点。你想想看,一个模型在训练时精度再高,部署后跑不起来等于零。
2.2 模型格式转换
2.2.1 ONNX:模型界的通用语言
ONNX是什么?它就是个中间格式。好比你把中文文档翻译成英文,再让不同国家的人都能看懂。ONNX就是那个「英文」。
我建议所有部署项目都先走ONNX。原因很简单:生态最全。不管你是PyTorch、TensorFlow还是PaddlePaddle,都能导出ONNX。而且TensorRT、OpenVINO这些推理引擎都优先支持ONNX。
来个实际例子。PyTorch转ONNX的代码长这样:
import torch
import torch.onnx
# 假设你有个训练好的模型
model = torch.load('resnet50.pth')
model.eval()
# 构造一个虚拟输入
dummy_input = torch.randn(1, 3, 224, 224)
# 导出ONNX
torch.onnx.export(
model,
dummy_input,
'resnet50.onnx',
opset_version=11, # 我一般用11或13
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'}} # 支持动态batch
)
小技巧:导出时加上dynamic_axes参数,这样你的模型就能处理不同batch size的输入。我在做视频分析项目时,就因为没加这个参数,结果每帧都要重新导出模型,效率极低。
2.2.2 TensorRT:NVIDIA的加速神器
TensorRT是NVIDIA推出的推理优化引擎。它做了三件事:层融合、精度校准、内存优化。说白了就是把模型里能合并的计算合并,能降低精度的降低精度,让GPU跑得更快。
我曾经在一个自动驾驶项目里,把ResNet-50从ONNX转成TensorRT,推理速度提升了3倍。怎么做到的?
import tensorrt as trt
# 创建builder
logger = trt.Logger(trt.Logger.WARNING)
builder = trt.Builder(logger)
# 创建网络定义
network = builder.create_network(
1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH)
)
# 解析ONNX模型
parser = trt.OnnxParser(network, logger)
with open('resnet50.onnx', 'rb') as f:
parser.parse(f.read())
# 构建引擎
config = builder.create_builder_config()
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 1 << 30) # 1GB
serialized_engine = builder.build_serialized_network(network, config)
避坑指南:我曾经因为没设置EXPLICIT_BATCH标志,结果模型推理时batch size死活不对。后来查文档才发现,TensorRT 8.0之后必须显式指定batch维度。嗯,这个坑我替你们踩过了。
2.3 模型量化与压缩
2.3.1 为什么要量化?
你想想看,一个FP32的模型参数占4个字节,INT8只占1个字节。量化就是把模型从FP32变成INT8,体积直接缩小4倍,推理速度也能提升2-4倍。代价是什么?精度会掉一点点,但通常可以接受。
我个人的经验是:大部分CV模型量化后精度损失在1%以内。但NLP模型就比较敏感,尤其是BERT这类,量化后可能掉3-5个点。
2.3.2 量化的两种方式
| 方式 | 原理 | 适用场景 | 精度损失 |
|---|---|---|---|
| 训练后量化(PTQ) | 用少量校准数据统计量化参数 | 大部分场景 | 较小 |
| 量化感知训练(QAT) | 在训练中模拟量化误差 | 精度要求高的场景 | 极小 |
我在项目中遇到过这种情况:PTQ量化后模型精度掉了2%,客户不接受。后来换成QAT,精度只掉了0.3%,顺利交付。所以我的建议是:先试PTQ,不行再上QAT。
2.3.3 模型压缩的其他手段
除了量化,还有几种压缩方法:
- 剪枝:去掉不重要的权重连接。我试过剪掉30%的参数,精度几乎不变。
- 知识蒸馏:用大模型教小模型。说白了就是「师傅带徒弟」。
- 权重共享:让多个层共用同一组参数。
实战建议:别一上来就搞剪枝和蒸馏。先做量化,通常能解决80%的性能问题。如果还不够,再考虑更复杂的手段。我曾经在一个项目里,光量化就把推理速度从30ms降到了8ms,客户直接说「够了够了」。
2.4 本章小结
模型部署这件事,说难不难,说简单也不简单。核心就三点:
- 格式转换:ONNX是中间桥梁,TensorRT是加速利器
- 量化压缩:INT8量化是性价比最高的优化手段
- 工程思维:先跑通,再优化,别一上来就追求极致
我记得刚入行时,总觉得部署就是「调个API就完事」。后来被现实教育了——模型部署涉及硬件、框架、算子、内存管理一堆东西。但别怕,跟着这门课一步步来,你也能成为部署高手。
下章预告:我们会深入TensorRT的算子融合和动态shape处理,这些都是实战中绕不开的硬骨头。
公众号:蓝海资料掘金营,微信deep3321