环境搭建:Python虚拟环境配置、ONNX Runtime安装、ONNX opset版本选择

好,咱们正式开始动手了。

这一章,说白了就是搭台子。台子搭不好,后面唱戏全得摔跟头。我见过太多同学,模型导出报错、推理结果不对,最后发现是环境版本打架。嗯,咱们今天就把这事彻底理清楚。

Python虚拟环境:别偷懒,这是底线

我个人习惯,每个项目都开独立的虚拟环境。为什么?你想想看,项目A用ONNX Runtime 1.12,项目B用1.15,要是装在一个全局环境里,迟早出幺蛾子。

我推荐用 conda 或者 venv。如果你主要做深度学习,conda更方便,因为它能顺带管理CUDA和cuDNN的版本。

我的标准操作流程:

# 创建Python 3.8环境(我个人最推荐的版本)
conda create -n onnx_deploy python=3.8

# 激活环境
conda activate onnx_deploy

# 如果喜欢用venv也行
python -m venv onnx_deploy
source onnx_deploy/bin/activate  # Linux/Mac
# onnx_deploy\Scripts\activate   # Windows

为什么推荐Python 3.8?我在项目中踩过坑——Python 3.10以上某些ONNX Runtime的旧版本不支持,而3.7又太老,很多新库已经放弃维护了。3.8是个黄金平衡点。

小技巧: 创建环境时顺手把pip升到最新,能避免很多依赖解析的奇怪报错。

pip install --upgrade pip

ONNX Runtime安装:选对版本很重要

ONNX Runtime有三种安装方式,我按推荐度排序:

  1. CPU版本pip install onnxruntime
  2. GPU版本pip install onnxruntime-gpu
  3. 直接编译:源码编译,不推荐新手尝试

这里有个坑——我曾经以为GPU版本肯定比CPU版本快,结果在树莓派上装了个GPU版,跑都跑不起来。说白了,你得先搞清楚目标平台有没有CUDA。

警告: 别在ARM架构的板子上装onnxruntime-gpu,它只支持x86_64的NVIDIA显卡。我见过有人拿Jetson Nano装这个,折腾了两天...

对于嵌入式部署,我建议这样选:

目标平台 推荐安装方式 备注
PC端(有NVIDIA显卡) onnxruntime-gpu 需要CUDA 11.x + cuDNN 8.x
PC端(无显卡) onnxruntime CPU推理,够用
ARM开发板(如树莓派) onnxruntime 或者用ONNX Runtime的ARM预编译包
Jetson系列 源码编译或JetPack自带 别用pip直接装,会哭

验证安装是否成功:

python -c "import onnxruntime; print(onnxruntime.__version__)"
# 如果能打印出版本号,比如 '1.15.0',就说明装好了

ONNX opset版本选择:别小看这个数字

opset,全称是Operator Set。它定义了ONNX支持哪些算子,以及这些算子的行为。说白了,opset版本越高,支持的算子越新,但兼容性可能越差。

我刚开始做部署时,觉得opset版本越高越好,直接选了21。结果模型导出到板子上,算子不支持,报错报得我头皮发麻。

后来我总结了一套选择策略:

  • PC端部署:选opset 15-18,新算子支持好,性能也稳定
  • 嵌入式部署:选opset 11-13,兼容性最好,老算子基本都支持
  • 特殊需求:比如要用到最新的Transformer算子,才考虑opset 19+

我的经验: 如果你不确定,就选opset 13。这个版本是个分水岭——它支持了大部分常用算子,而且几乎所有推理框架都兼容。我在RK3588、树莓派4B、Jetson Nano上都验证过,稳得很。

怎么在导出时指定opset版本?以PyTorch为例:

import torch
import torch.onnx

# 假设你有一个训练好的模型
model = YourModel()
dummy_input = torch.randn(1, 3, 224, 224)

# 指定opset版本为13
torch.onnx.export(
    model,
    dummy_input,
    "model.onnx",
    opset_version=13,  # 这里!关键!
    input_names=["input"],
    output_names=["output"]
)

注意: 如果你用了某些高级算子(比如Einsum、ScatterND),低版本opset可能不支持。这时候要么升级opset,要么手动替换算子。我曾经为了一个ScatterND算子,把整个模型结构都改了...嗯,那是个教训。

环境验证:跑个简单的例子

环境搭好了,咱们跑个Hello World验证一下:

import onnxruntime as ort
import numpy as np

# 创建一个简单的ONNX模型(这里用代码生成,实际部署时是加载文件)
# 假设你已经有了一个model.onnx文件
session = ort.InferenceSession("model.onnx")

# 准备输入数据
input_name = session.get_inputs()[0].name
input_shape = session.get_inputs()[0].shape
input_data = np.random.randn(*input_shape).astype(np.float32)

# 推理
outputs = session.run(None, {input_name: input_data})

print("推理成功!输出形状:", outputs[0].shape)

如果这段代码能跑通,恭喜你,环境搭建成功了。如果报错,别慌——90%的情况是版本不匹配。检查一下Python版本、ONNX Runtime版本、opset版本,三者要能对上。

总结一下今天的内容:

  • 用conda创建独立的Python 3.8环境
  • 根据目标平台选择ONNX Runtime版本
  • 嵌入式部署优先选opset 13
  • 跑个简单推理验证环境

下一章,咱们开始讲模型导出。到时候你会感谢今天把环境搭好的自己——因为导出时遇到的各种奇葩问题,90%都是环境没配好导致的。嗯,我当年就是这么过来的。