1、ONNX基础认知:什么是ONNX、为什么需要ONNX、ONNX的生态与优势
1.1 什么是ONNX?说白了就是个模型“通用语言”
ONNX,全称是Open Neural Network Exchange。名字挺长,但核心就一句话:它是深度学习模型的“通用交换格式”。
我刚开始接触AI部署那会儿,最头疼的就是模型格式不统一。PyTorch训练好的模型,想部署到TensorRT上?得先转成.pt,再转成.wts,再转成.engine……中间但凡有个版本对不上,直接报错。后来ONNX出现了,大家约定好:你训练完,先导出成.onnx,剩下的部署工作我来搞定。
说白了,ONNX就像USB接口。不管你的设备是苹果、安卓还是Windows,只要插上USB,就能传输数据。ONNX就是AI模型界的USB。
核心定义:ONNX是一种开放的、跨平台的深度学习模型表示格式。它定义了一套标准化的算子集和计算图描述方式,让模型可以在不同框架之间自由迁移。
1.2 为什么需要ONNX?——我踩过的坑告诉你
你可能觉得:“我用PyTorch训练,用PyTorch推理不就行了?干嘛多此一举?”
嗯,这个问题我当年也问过。直到我在项目中遇到这几个场景:
- 场景一:训练用PyTorch,部署用TensorRT——PyTorch的推理速度在GPU上还行,但到了边缘设备(比如Jetson Nano)上,TensorRT能快3-5倍。没有ONNX,你得手动写转换脚本,一个算子一个算子地调。
- 场景二:团队里有人用PyTorch,有人用TensorFlow——模型交接时,对方说“你转成.pb给我”,你心里一万个不情愿。有了ONNX,大家统一导出.onnx,谁都不用迁就谁。
- 场景三:模型要跑在手机端(CoreML)或浏览器端(WebGL)——这些平台只认自己的格式。ONNX就像中间人,帮你把模型“翻译”成目标平台能懂的语言。
我曾经有个项目,客户要求模型必须跑在华为昇腾芯片上。昇腾的推理引擎只支持ONNX和Caffe。我花了三天把PyTorch模型转成ONNX,又花了一天调精度对齐。如果没有ONNX,我可能得重写整个推理代码——那画面太美我不敢看。
我的建议:无论你用什么框架训练,养成导出ONNX的习惯。哪怕你现在用不到,将来某天客户突然说“我要部署在xxx上”,你会感谢自己当初多存了一份.onnx文件。
1.3 ONNX的生态与优势——它凭什么这么火?
ONNX能火,不是靠吹的。它的生态,说白了就是“大家都来玩”。
1.3.1 框架支持:几乎全覆盖
| 框架 | 导出ONNX | 导入ONNX | 备注 |
|---|---|---|---|
| PyTorch | ✅ torch.onnx.export | ✅ onnx2pytorch | 官方支持,最成熟 |
| TensorFlow | ✅ tf2onnx | ✅ onnx2tf | 需要额外工具 |
| Keras | ✅ keras2onnx | ✅ onnx2keras | 社区维护 |
| MXNet | ✅ mxnet2onnx | ✅ onnx2mxnet | 官方支持 |
| PaddlePaddle | ✅ paddle2onnx | ✅ onnx2paddle | 百度官方支持 |
1.3.2 推理引擎支持:你想得到的都有
ONNX模型训练好之后,能跑在哪些推理引擎上?我列几个常用的:
- ONNX Runtime:微软出品,CPU/GPU都支持,性能优秀。我个人最常用这个做快速验证。
- TensorRT:NVIDIA的GPU加速引擎。ONNX转TensorRT,是很多高性能部署场景的标准流程。
- OpenVINO:Intel的推理引擎,专门优化CPU和集成显卡。我在边缘设备上经常用。
- CoreML:苹果的移动端推理引擎。ONNX转CoreML,就能跑在iPhone上。
- NCNN / MNN:腾讯和阿里巴巴的移动端引擎。ONNX转NCNN,是很多Android端AI应用的标配。
一句话总结:ONNX的生态,就是“一次导出,到处运行”。你只需要维护一份模型文件,剩下的交给ONNX生态去适配。
1.3.3 ONNX的优势——为什么我推荐你学?
除了生态,ONNX本身还有几个硬核优势:
- 标准化算子集:ONNX定义了100多个标准算子(Conv、Relu、BatchNorm等)。不同框架的算子,只要映射到ONNX标准,就能互通。我遇到过有些框架的算子实现有细微差异,ONNX帮我们统一了行为。
- 计算图优化:ONNX模型可以做一些图级别的优化,比如常量折叠、算子融合。这些优化在推理时能明显提速。我记得有一次,一个ResNet50模型,ONNX Runtime比PyTorch原生推理快了15%。
- 量化支持:ONNX支持INT8、FP16等低精度量化。对于边缘设备,量化后模型大小能缩小4倍,速度提升2-3倍。我做过一个项目,模型从FP32量化到INT8,精度只掉了0.3%,但推理速度翻了一倍。
- 跨平台:Windows、Linux、macOS、Android、iOS……ONNX都能跑。你想想看,一个模型文件,从服务器到手机,从云端到边缘,全都能用,这得多省事。
注意:ONNX不是万能的。有些自定义算子(比如你自己写的CUDA kernel)可能不支持。遇到这种情况,要么用ONNX的自定义算子扩展,要么老老实实写原生推理代码。我建议:训练时尽量用标准算子,少搞花活。
1.4 一个简单的ONNX导出示例
光说不练假把式。我写个最简单的PyTorch模型导出ONNX的例子,你感受一下:
import torch
import torch.nn as nn
# 定义一个简单的模型
class SimpleModel(nn.Module):
def __init__(self):
super().__init__()
self.conv = nn.Conv2d(3, 16, 3)
self.relu = nn.ReLU()
self.pool = nn.AdaptiveAvgPool2d(1)
self.fc = nn.Linear(16, 10)
def forward(self, x):
x = self.conv(x)
x = self.relu(x)
x = self.pool(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
# 创建模型和虚拟输入
model = SimpleModel()
dummy_input = torch.randn(1, 3, 224, 224)
# 导出ONNX
torch.onnx.export(
model,
dummy_input,
"simple_model.onnx",
input_names=["input"],
output_names=["output"],
dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}}
)
print("ONNX模型导出成功!")
这段代码跑完,你会在当前目录下看到一个simple_model.onnx文件。用Netron打开它,就能看到完整的计算图结构。嗯,是不是很简单?
小技巧:导出时加上dynamic_axes参数,可以让模型支持动态batch size。这样部署时,你就不用固定输入尺寸了。我习惯在导出时都加上这个,省得后面改。
1.5 本章小结
这一章我们聊了:
- ONNX是什么——模型界的“通用语言”
- 为什么需要ONNX——解决框架碎片化、跨平台部署的痛点
- ONNX的生态——框架支持、推理引擎支持、标准化优势
- 一个简单的导出示例——让你亲手感受ONNX的便利
下一章,我会带你深入ONNX的内部结构,看看一个.onnx文件里到底藏着什么。到时候,你会对“计算图”这个概念有更直观的理解。
记住:ONNX不是终点,它是连接训练和部署的桥梁。把这座桥搭好了,后面的路就好走了。