2、ONNX 基础:ONNX 是什么、ONNX 的生态与优势、ONNX 的安装与验证

2.1 ONNX 到底是什么?

ONNX,全称 Open Neural Network Exchange。

说白了,它就是一个「模型通用格式」。你想想看,PyTorch 训练出来的模型是 .pt 文件,TensorFlow 是 .pb 文件,Keras 是 .h5 文件……每个框架都有自己的「方言」。ONNX 就是给这些方言配了个「普通话」标准。

我刚开始做模型部署那会儿,最头疼的就是框架切换。客户那边用 TensorFlow,我这边用 PyTorch,每次对接都要重写推理代码。后来接触了 ONNX,才发现原来可以这么省事。

ONNX 的核心思想很简单:定义一套统一的算子集合和计算图表示。不管你是用哪个框架训练的,只要导出成 ONNX 格式,就能在任何支持 ONNX 的推理引擎上运行。

核心要点:

  • ONNX 是一种开放标准,不是某个公司的私有格式
  • 它描述的是计算图,不是训练过程
  • 它只负责推理,不负责训练

2.2 ONNX 的生态与优势

ONNX 的生态,我愿称之为「模型转换界的瑞士军刀」。为什么这么说?

2.2.1 框架支持广泛

目前主流的深度学习框架都原生支持 ONNX 导出:

框架 导出方式 我踩过的坑
PyTorch torch.onnx.export() 动态轴要显式指定,不然导出后 batch size 被固定
TensorFlow tf2onnx 工具 某些自定义 op 需要手动注册转换规则
Keras tf2onnx 或 keras2onnx Lambda 层经常出问题,建议用函数式 API
PaddlePaddle paddle2onnx 这个相对成熟,我基本没遇到大问题

2.2.2 推理后端丰富

ONNX 模型可以跑在多种推理引擎上:

  • ONNX Runtime:微软出品,性能优化做得很好
  • TensorRT:NVIDIA 的 GPU 加速方案,支持 ONNX 直接导入
  • OpenVINO:Intel 的 CPU/VPU 加速方案
  • CoreML:Apple 的移动端推理框架

我记得有一次项目需要在树莓派上跑模型。客户要求用 CPU 推理,还不能太慢。我试了直接跑 PyTorch 模型,帧率只有 2 FPS。后来转成 ONNX,再用 ONNX Runtime 跑,直接飙到 15 FPS。嗯,这就是 ONNX 的魅力。

2.2.3 算子标准化

ONNX 定义了一套标准算子集(opsets)。每个版本都会增加新的算子。这意味着:

  • 不同框架的相同功能算子,在 ONNX 里是统一的
  • 算子版本号清晰,方便排查兼容性问题
  • 社区贡献的算子扩展,可以跨框架使用

我的建议:刚开始接触 ONNX 时,尽量使用 opset 11 或 12。这两个版本比较稳定,算子覆盖也全。太新的 opset 可能某些推理后端还不支持。

2.3 ONNX 的安装与验证

安装 ONNX 其实很简单。但我要提醒你:千万别直接 pip install onnx 就完事了。我吃过这个亏。

2.3.1 安装 ONNX 核心库

# 基础安装
pip install onnx

# 推荐安装(包含常用工具)
pip install onnx onnxruntime onnxconverter-common

为什么推荐装 onnxruntime?因为光有 onnx 库只能做模型检查和转换,不能真正跑推理。onnxruntime 才是那个「跑起来」的引擎。

2.3.2 安装 ONNX Runtime

根据你的硬件平台选择:

场景 安装命令 说明
CPU 推理 pip install onnxruntime 通用,所有平台都支持
GPU 推理 pip install onnxruntime-gpu 需要 CUDA 和 cuDNN
移动端 pip install onnxruntime-mobile 体积小,适合 ARM 架构

注意:我曾经在 GPU 服务器上装错了版本。明明有显卡,却装了 CPU 版的 onnxruntime,结果推理速度慢得离谱。检查了半天才发现是安装问题。所以安装前一定确认好:pip list | grep onnxruntime 看看版本对不对。

2.3.3 验证安装是否成功

装完之后,跑个简单的验证脚本:

import onnx
import onnxruntime as ort

# 1. 检查 onnx 库是否可用
print(f"ONNX 版本: {onnx.__version__}")

# 2. 检查 onnxruntime 是否可用
print(f"ONNX Runtime 版本: {ort.__version__}")

# 3. 创建一个最简单的 ONNX 模型来验证
import numpy as np

# 创建一个简单的加法模型
def create_simple_model():
    # 这里用 onnx.helper 手动构建
    X = onnx.helper.make_tensor_value_info('X', onnx.TensorProto.FLOAT, [None, 3])
    Y = onnx.helper.make_tensor_value_info('Y', onnx.TensorProto.FLOAT, [None, 3])
    
    add_node = onnx.helper.make_node(
        'Add',
        inputs=['X', 'Y'],
        outputs=['Z']
    )
    
    graph = onnx.helper.make_graph(
        [add_node],
        'test_graph',
        [X, Y],
        [onnx.helper.make_tensor_value_info('Z', onnx.TensorProto.FLOAT, [None, 3])]
    )
    
    model = onnx.helper.make_model(graph)
    return model

model = create_simple_model()

# 4. 检查模型是否合法
onnx.checker.check_model(model)
print("模型检查通过!")

# 5. 用 onnxruntime 跑一下推理
session = ort.InferenceSession(model.SerializeToString())
input_data = np.array([[1.0, 2.0, 3.0]], dtype=np.float32)
output = session.run(None, {'X': input_data, 'Y': input_data})
print(f"推理结果: {output[0]}")

如果看到输出类似:

ONNX 版本: 1.14.0
ONNX Runtime 版本: 1.16.0
模型检查通过!
推理结果: [[2. 4. 6.]]

恭喜你,ONNX 环境已经搭好了。

2.3.4 常见安装问题

我整理了几个高频问题:

  • 问题:ImportError: No module named 'onnx'
    解决:检查是否在正确的 Python 环境里。用 which python 确认一下。
  • 问题:onnxruntime 安装后报 DLL 加载失败
    解决:Windows 上常见。安装 Microsoft Visual C++ Redistributable 即可。
  • 问题:GPU 版 onnxruntime 找不到 CUDA
    解决:检查 CUDA 版本是否匹配。onnxruntime-gpu 1.16 需要 CUDA 11.8。

一个小技巧:如果你不确定该装哪个版本,直接用 pip install onnxruntime 装 CPU 版。等模型转换成功后,再根据部署环境决定要不要换 GPU 版。这样能避免很多兼容性问题。

好了,ONNX 的基础就这些。下一章我们会真正动手,把一个 PyTorch 模型转成 ONNX。到时候你会发现,原来模型转换可以这么简单。