1. ONNX基础认知:什么是ONNX、ONNX的诞生背景与生态定位、ONNX在AI部署中的核心价值

1.1 什么是ONNX?一个模型,到处跑

ONNX,全称是Open Neural Network Exchange。中文叫「开放神经网络交换格式」。说白了,它就是一种模型中间格式。

我经常跟团队新人这么解释:你训练模型时用PyTorch,同事用TensorFlow,隔壁组用MXNet。大家各玩各的,模型文件互不兼容。这时候ONNX就派上用场了——它像一个通用翻译器,把各家框架的模型都转成同一种「语言」。

举个例子。你用PyTorch训练了一个ResNet50,保存为.pth文件。这个文件TensorFlow读不了,ONNX Runtime也读不了。但如果你把它导出成.onnx文件,那几乎所有主流推理引擎都能加载。嗯,这就是ONNX的核心价值。

一句话总结:ONNX是AI模型的「通用语言」。它让模型训练和模型部署解耦,你爱用什么框架训练都行,部署时统一用ONNX。

1.2 ONNX的诞生背景——为什么需要它?

2017年之前,AI部署是个大坑。我那时候做项目,模型用Caffe训练,部署到移动端得转成NCNN。转格式的过程简直噩梦——算子不支持、精度对不上、各种魔改代码。一个模型转两周是常事。

为什么会这样?因为每个深度学习框架都有自己的模型格式。PyTorch用.pt,TensorFlow用.pb或.savedmodel,Keras用.h5。这些格式之间没有统一标准。你训练时用PyTorch,部署时想用TensorRT加速?对不起,先转一圈吧。

2017年9月,微软和Facebook联合推出了ONNX。后来亚马逊、英特尔、AMD、NVIDIA等巨头纷纷加入。大家坐在一起定了个规矩:以后模型训练完,先导出成ONNX格式,然后各个推理框架都去支持ONNX。这样一次导出,到处部署。

我个人觉得,ONNX的诞生是AI工程化进程中的一个里程碑。它把「训练」和「部署」这两个环节彻底解耦了。你想想看,没有ONNX之前,算法工程师得学一堆推理框架的API,有了ONNX之后,你只需要关心模型本身。

1.3 ONNX的生态定位——它在AI部署链中扮演什么角色?

ONNX在整个AI部署流程中,处于中间位置。我画个简单的链路:

训练框架(PyTorch/TF/Paddle) → ONNX模型 → 推理引擎(ONNX Runtime/TensorRT/OpenVINO) → 硬件设备(CPU/GPU/NPU)

ONNX不是推理引擎,也不是训练框架。它就是个「中间人」。但这个中间人极其重要。

我遇到过不少团队,直接拿PyTorch模型做推理。这在原型验证阶段没问题,但到了生产环境就露馅了——PyTorch的推理性能远不如专门的推理引擎。而ONNX就是通往这些高性能推理引擎的桥梁。

目前ONNX生态包含几个关键部分:

  • ONNX格式本身:定义模型结构和权重的标准格式
  • ONNX Runtime:微软开源的跨平台推理引擎,直接加载ONNX模型
  • ONNX算子集:定义了标准化的神经网络算子,比如Conv、Relu、Gemm等
  • 各框架的导出工具:torch.onnx.export、tf2onnx、paddle2onnx等

小提示:ONNX Runtime只是ONNX生态的一部分。很多人以为ONNX就等于ONNX Runtime,其实不是。ONNX是一种格式,ONNX Runtime是读取这种格式的引擎之一。你完全可以把ONNX模型部署到TensorRT或OpenVINO上。

1.4 ONNX在AI部署中的核心价值

我做了五六年模型部署,总结下来ONNX有四个核心价值:

1.4.1 跨框架互操作性

这是ONNX最直接的价值。你用PyTorch训练,用TensorRT推理?没问题。你用Keras训练,用ONNX Runtime部署?也可以。ONNX打破了框架之间的壁垒。我曾经有个项目,甲方要求用TensorFlow,但我们团队只熟悉PyTorch。最后方案就是PyTorch训练→导出ONNX→交付给甲方。双方都满意。

1.4.2 推理性能优化

ONNX模型可以被各种推理引擎深度优化。比如ONNX Runtime有图优化、算子融合、内存复用等技巧。TensorRT更是能把ONNX模型编译成针对NVIDIA GPU的极致优化版本。我实测过,同样的模型,PyTorch直接推理和转ONNX后用TensorRT推理,速度能差3-5倍。

1.4.3 硬件适配能力

不同的硬件设备,支持的推理引擎不同。CPU上可以用ONNX Runtime或OpenVINO,GPU上可以用TensorRT,手机端可以用NCNN或MNN。ONNX模型可以灵活适配这些硬件。你不需要为每个硬件单独训练模型,一次导出,到处适配。

1.4.4 模型标准化与可调试性

ONNX模型是结构化的,可以用Netron等工具可视化。我调试模型时,经常把PyTorch模型和ONNX模型同时可视化,对比结构是否一致。ONNX还支持静态图,所有计算图在推理前就固定了,这比动态图更容易做优化和调试。

注意:ONNX不是万能的。有些算子PyTorch支持但ONNX不支持,导出时会报错。还有些模型转ONNX后精度会有微小损失。这些坑我们后面章节会详细讲怎么处理。

1.5 一个简单的ONNX模型示例

说了这么多理论,我们来看个实际的。下面是用PyTorch导出一个简单ONNX模型的代码:

import torch
import torch.nn as nn

# 定义一个简单的神经网络
class SimpleModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc = nn.Linear(10, 5)
        self.relu = nn.ReLU()
    
    def forward(self, x):
        x = self.fc(x)
        x = self.relu(x)
        return x

# 创建模型实例
model = SimpleModel()
model.eval()

# 创建示例输入
dummy_input = torch.randn(1, 10)

# 导出ONNX模型
torch.onnx.export(
    model,               # 模型
    dummy_input,         # 示例输入
    "simple_model.onnx", # 输出文件名
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={"input": {0: "batch_size"}}
)

print("ONNX模型导出成功!")

这段代码执行后,会生成一个simple_model.onnx文件。你可以用Netron打开看看,里面包含了网络结构、权重参数、输入输出信息等。嗯,这就是ONNX模型的基本形态。

我刚开始学ONNX时,就是从这个例子入手的。先跑通导出流程,然后用Netron看结构,最后用ONNX Runtime加载推理。三步走,很快就能上手。

1.6 本章小结

ONNX不是什么高深的技术,它就是一个模型中间格式。但它的出现,让AI部署从「各自为战」变成了「统一标准」。我个人觉得,如果你想做AI工程化、模型部署相关的工作,ONNX是必须掌握的一环。

下一章,我们会深入ONNX模型的结构——它到底长什么样?里面有哪些关键组件?怎么用代码解析一个ONNX模型?到时候见。