2. 环境搭建与工具链:安装ONNX、ONNX Runtime、protobuf及常见调试工具

说实话,环境搭建这事儿,看着简单,但坑是真不少。我见过太多同学在模型转换这一步卡住,最后发现是protobuf版本没对齐。嗯,咱们今天就把这事儿一次性捋清楚。

2.1 为什么这三样东西必须装?

你想想看,ONNX是个中间格式,它本身不负责推理。就像你写了个PDF文件,总得有个阅读器吧?ONNX Runtime就是那个阅读器。而protobuf呢,它是ONNX的底层序列化协议——说白了,就是定义模型结构该怎么存、怎么读的规则。

我个人的习惯是:先装protobuf,再装ONNX,最后装ONNX Runtime。这个顺序别搞反了,否则你会遇到一些莫名其妙的链接错误。

⚠️ 我曾经踩过的坑: 有一次我图省事,直接用pip装了onnx,没管protobuf。结果导出模型时一直报"Unknown field"错误。折腾了两小时,最后发现是系统自带的protobuf版本太旧(3.6.x),而ONNX需要3.11以上。从那以后,我再也不敢跳过protobuf的版本检查了。

2.2 protobuf 安装与版本选择

protobuf分两部分:一个是编译器 protoc,一个是Python绑定的 protobuf 包。两者版本必须匹配。

推荐版本:

组件 推荐版本 说明
protoc (编译器) 3.21.12 这个版本最稳定,兼容ONNX 1.14+
protobuf (Python) 3.21.12 必须和protoc版本一致

安装命令:

# 1. 安装protoc编译器(Linux/Mac)
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.21.12/protoc-3.21.12-linux-x86_64.zip
unzip protoc-3.21.12-linux-x86_64.zip -d /usr/local/protoc
export PATH=$PATH:/usr/local/protoc/bin

# 2. 安装Python包
pip install protobuf==3.21.12

# 3. 验证
protoc --version  # 应该输出 libprotoc 3.21.12
python -c "import google.protobuf; print(google.protobuf.__version__)"  # 应该输出 3.21.12
💡 小技巧: 如果你在Windows上,建议直接用conda装:conda install protobuf=3.21.12。conda会自动帮你处理编译器路径问题,省心很多。

2.3 ONNX 安装

ONNX的安装其实很简单,但要注意:不要用pip install onnx直接装最新版。我建议指定版本,因为不同版本的ONNX对算子支持有差异。

# 推荐安装1.14.1(稳定且功能完整)
pip install onnx==1.14.1

# 验证安装
python -c "import onnx; print(onnx.__version__)"

装完之后,我建议你立刻跑一个简单的测试:

import onnx
import onnx.helper as helper

# 创建一个最简单的模型:输入 -> 输出
input = helper.make_tensor_value_info('input', onnx.TensorProto.FLOAT, [1, 3, 224, 224])
output = helper.make_tensor_value_info('output', onnx.TensorProto.FLOAT, [1, 3, 224, 224])

node = helper.make_node('Relu', ['input'], ['output'])
graph = helper.make_graph([node], 'test_graph', [input], [output])
model = helper.make_model(graph)

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

如果这段代码能跑通,说明你的ONNX环境基本没问题了。

2.4 ONNX Runtime 安装

ONNX Runtime分CPU版和GPU版。我个人建议:开发阶段先用CPU版,调试方便;部署时再切GPU版

CPU版安装:

pip install onnxruntime==1.16.3

GPU版安装(需要CUDA 11.8 + cuDNN 8.6):

pip install onnxruntime-gpu==1.16.3
⚠️ 注意: GPU版对CUDA版本要求非常严格。我遇到过好几次,明明CUDA装好了,但onnxruntime-gpu就是找不到GPU。后来发现是cuDNN版本没对齐。建议用 nvidia-sminvcc --version 先确认你的CUDA版本,再去ONNX Runtime官网查对应的兼容矩阵。

验证GPU是否可用:

import onnxruntime as ort
print(ort.get_device())  # 如果是GPU版且可用,输出 "GPU"
print(ort.get_available_providers())  # 列出所有可用的执行提供程序

2.5 常见调试工具

光有运行环境还不够,调试工具才是救命稻草。我平时最常用的有这几个:

工具 用途 安装方式
Netron 可视化模型结构 pip install netron
onnx-simplifier 简化模型,去除冗余算子 pip install onnx-simplifier
onnx2txt 将ONNX模型转为文本,方便对比 pip install onnx2txt
polygraphy NVIDIA官方工具,调试精度问题 pip install polygraphy

Netron 的使用方法:

import netron
netron.start('your_model.onnx')  # 会在浏览器中打开可视化界面

我个人特别喜欢Netron的一点是:它能直接显示每个算子的输入输出形状。有一次我排查一个维度不对齐的问题,就是靠Netron一眼看出来的——某个卷积层的输出通道数比预期少了64。

onnx-simplifier 的使用:

python -m onnxsim your_model.onnx simplified_model.onnx

这个工具能帮你干掉模型里那些多余的Shape、Gather、Unsqueeze操作。我遇到过最夸张的一次,一个原本200MB的模型,简化后只剩120MB——里面塞了一大堆没用的常量节点。

💡 我的调试三板斧:
1. 先用Netron看结构,确认算子类型和连接关系
2. 用onnx-simplifier清理冗余节点
3. 用polygraphy对比原始模型和ONNX模型的输出差异(精度调试时必用)

2.6 环境验证脚本

最后,我建议你保存下面这个脚本。每次换机器或重装环境时,跑一遍就能确认所有组件是否就绪:

import sys
import onnx
import onnxruntime as ort
import google.protobuf

print(f"Python版本: {sys.version}")
print(f"ONNX版本: {onnx.__version__}")
print(f"ONNX Runtime版本: {ort.__version__}")
print(f"protobuf版本: {google.protobuf.__version__}")
print(f"推理设备: {ort.get_device()}")

# 检查protoc编译器
import subprocess
try:
    result = subprocess.run(['protoc', '--version'], capture_output=True, text=True)
    print(f"protoc编译器: {result.stdout.strip()}")
except:
    print("⚠️ protoc编译器未安装或不在PATH中")

好了,环境搭建这部分就到这儿。下一章咱们开始动手,把PyTorch模型转成ONNX——那才是真正有意思的地方。