在人工智能快速发展的今天,将模型部署到各种不同的平台——从云服务器到边缘设备——仍然是一项复杂的挑战。 ONNX (Open Neural Network Exchange) 作为一种开放标准,通过充当 AI 模型的通用“翻译器”来简化这一过程。本文将深入探讨 ONNX 导出 的工作原理、重要性,以及如何在您的项目中利用它,最终实现 模型可移植性

什么是ONNX?

ONNX 是一种用于表示机器学习模型的开放格式,由微软、Facebook (Meta) 和 AWS 共同开发。它允许在 PyTorch、TensorFlow 或 scikit-learn 等框架中训练的模型导出为一种通用的、可互操作的格式。 可以将 ONNX 视为机器学习领域的 PDF,一种可以在任何地方使用的标准化文件。这意味着无论您使用哪种深度学习框架进行模型训练,都可以通过 ONNX 格式,在不同的推理引擎上运行,实现 模型可移植性

ONNX 包含以下关键组件:

  • ONNX 模型格式: 一种基于 protobuf 的文件 (.onnx),用于存储模型架构、权重和元数据。它包含了模型的完整定义,包括各个层的类型、参数和连接关系。
  • ONNX Runtime: 一种用于高性能推理的跨平台引擎。它能够加载 ONNX 模型,并在不同的硬件平台上高效地执行推理计算。
  • 转换器: 诸如 torch.onnxtf2onnx 这样的工具,用于将模型从原生框架导出到 ONNX 格式。这些转换器负责将原生框架中的算子 (operators) 转换为 ONNX 定义的等效算子。

为什么要导出到ONNX?三大关键优势

将模型导出到 ONNX 具有以下三个关键优势:框架无关性、优化推理和跨平台部署,最终促进 模型可移植性

  • 框架无关性: 摆脱厂商锁定。您可以在 PyTorch 中训练模型,然后在 TensorRT 中部署。也可以混合使用工具,例如使用 PyTorch 进行原型设计,使用 ONNX Runtime 进行生产部署。这意味着您不再局限于特定框架的生态系统,可以自由选择最适合您需求的工具。 例如,一个公司可能使用 TensorFlow 开发模型,但希望将其部署到移动设备上。由于 TensorFlow Lite 在某些移动平台上的支持有限,他们可以将模型导出到 ONNX,然后使用 ONNX Runtime Mobile 在移动设备上运行,从而实现跨平台部署。

  • 优化推理: ONNX Runtime 应用特定于硬件的优化(CPU/GPU 加速、量化)。与原生框架相比,在生产环境中可以实现 2-4 倍的加速。ONNX Runtime 内置了许多优化技术,例如算子融合、常量折叠和内存优化,可以显著提高模型的推理速度。它还支持多种加速后端,例如 CUDA、TensorRT 和 OpenVINO,可以充分利用硬件资源来加速推理。例如,在CPU上做模型推理,使用OpenVINO加速可以获得明显的性能提升。

    • 案例: 假设您有一个图像识别模型,需要在高吞吐量的服务器上运行。通过将模型导出到 ONNX 并使用 ONNX Runtime 的 GPU 加速功能,您可以显著提高模型的推理速度,从而降低服务器成本。实际测试表明,在使用 ONNX Runtime 和 GPU 加速后,模型的吞吐量可以提高 3 倍以上。
  • 跨平台部署: 无缝部署到云端(Azure ML、AWS SageMaker)、边缘设备(IoT 设备)、移动设备(通过 ONNX Runtime Mobile 在 iOS/Android 上)和浏览器(通过 ONNX.js)。这意味着您可以将模型部署到任何地方,无论您的目标平台是什么。这种灵活性对于那些需要在多个平台上部署模型的企业来说至关重要。 例如,一个智能家居公司可能需要在云端处理用户数据,在边缘设备上进行实时分析,并在移动应用上显示结果。通过使用 ONNX,他们可以将同一个模型部署到所有这些平台上,而无需进行任何修改,从而简化了开发和部署流程。

导出模型:快速教程

以下是将 PyTorch 模型导出到 ONNX 的示例:

import torch
import torchvision

# 加载预训练的 ResNet18 模型
model = torchvision.models.resnet18(pretrained=True)
model.eval()

# 创建虚拟输入(匹配模型的预期形状)
dummy_input = torch.randn(1, 3, 224, 224)

# 导出到 ONNX
torch.onnx.export(
    model,
    dummy_input,
    "resnet18.onnx",
    opset_version=15,  # ONNX 算子集版本
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}}  # 启用动态批处理
)

关键参数:

  • opset_version: ONNX 算子集 (operator set) 版本 (确保与目标运行时兼容)。不同的 ONNX Runtime 版本可能支持不同的算子集。
  • dynamic_axes: 允许可变的批大小 (对于可扩展的服务至关重要)。这使得模型可以处理不同大小的输入,而无需重新编译或重新加载模型。

对于 TensorFlow,请使用 tf2onnx:

python -m tf2onnx.convert \
  --saved-model path/to/saved_model \
  --output model.onnx

ONNX 生态系统:超越导出

ONNX 生态系统不仅仅包含模型导出工具,还包括运行时、优化工具和验证工具,形成了一个完整的解决方案,以支持 模型可移植性

  • 运行时:

    • ONNX Runtime: 支持 CPU/GPU/NPU 加速和量化。
    • TensorRT: NVIDIA 的高性能运行时,适用于 ONNX 模型。
  • 优化工具:

    • 使用 onnxoptimizer 修剪冗余算子。
    • 使用 onnxruntime.quantization 量化模型。
  • 验证:

    • 使用 onnx.checker.check_model() 检查模型有效性。
    • 使用 Netron 可视化模型。

常见陷阱与最佳实践

在使用 ONNX 时,需要注意一些常见陷阱,并遵循最佳实践,以确保模型的正确性和性能。

  • 算子支持: 并非所有特定于框架的算子(例如,PyTorch 的 nn.LSTM)都与 ONNX 兼容。

    • 解决方法: 使用标准算子或通过 ONNXopset_version 使用自定义算子。如果您的模型使用了 ONNX 不支持的算子,您可以尝试使用等效的标准算子来替换它,或者使用 ONNX 的自定义算子功能来扩展 ONNX 的算子集。
  • 形状/类型不匹配: 确保训练和导出之间的输入形状/类型匹配。

    • 提示: 在导出期间使用 onnxruntime 进行推理测试。这可以帮助您及早发现潜在的问题,例如输入形状不匹配或数据类型错误。
  • 性能调优: 利用 ONNX Runtime 的图优化:

sess_options = onnxruntime.SessionOptions()
sess_options.graph_optimization_level = onnxruntime.GraphOptimizationLevel.ORT_ENABLE_ALL

案例: 某公司在使用 PyTorch 开发了一个自然语言处理模型,并将其导出到 ONNX。然而,在部署到生产环境后,他们发现模型的推理速度非常慢。经过分析,他们发现 ONNX 图中存在大量的冗余算子,导致性能下降。通过使用 onnxoptimizer 修剪冗余算子,模型的推理速度提高了 2 倍以上。

ONNX的未来

ONNX 正在扩展到神经网络之外:

  • ONNX-ML: 支持传统的 ML 模型(scikit-learn、XGBoost)。
  • MicroML: 适用于微控制器的轻量级运行时(例如 Arduino)。
  • 与开放标准集成: 与 Apache TVM、MLIR 合并。

ONNX 不断演进,以适应新的技术趋势和应用场景。例如, ONNX-ML 的出现使得可以将传统的机器学习模型也导出到 ONNX 格式,从而实现与深度学习模型的统一部署。 MicroML 则使得可以在资源受限的设备上运行机器学习模型,为物联网应用带来了新的可能性。

ONNX、TensorFlow Lite和CoreML的对比

虽然 ONNX、TensorFlow Lite 和 CoreML 都旨在解决模型部署的问题,但它们在设计理念、目标平台和功能特性上存在一些差异。以下是对这三种技术的简要对比:

| 特性 | ONNX | TensorFlow Lite | CoreML |
| ————- | ——————————————————————— | ———————————————————————– | ———————————————————————- |
| 设计理念 | 框架无关性,跨平台部署 | 专注于移动和嵌入式设备 | 专注于苹果生态系统 |
| 目标平台 | 云端、边缘设备、移动设备、浏览器 | 移动设备、嵌入式设备、IoT 设备 | iOS、macOS、watchOS、tvOS |
| 框架支持 | 支持多种框架(PyTorch、TensorFlow、scikit-learn 等) | 主要支持 TensorFlow | 主要支持 CoreML Tools 转换的模型 |
| 优化 | 支持多种优化技术(量化、剪枝、算子融合等),依赖 ONNX Runtime 提供的优化 | 提供模型量化工具,针对移动设备进行优化 | 针对苹果硬件进行优化 |
| 易用性 | 需要使用转换器将模型转换为 ONNX 格式,集成相对复杂 | 提供易于使用的 API,集成相对简单 | 提供易于使用的 API,集成非常简单 |
| 社区支持 | 社区活跃,文档完善 | 社区活跃,文档完善 | 主要由苹果维护,文档相对完善 |
| 模型安全性 | 依赖于 ONNX Runtime 提供的安全机制 | 依赖于 TensorFlow Lite 提供的安全机制 | 依赖于苹果提供的安全机制 |
| 模型可移植性 | 最佳 | 较好,但主要集中在移动和嵌入式设备 | 局限于苹果生态系统 |

总的来说, ONNX模型可移植性 方面具有明显的优势,可以支持多种框架和平台。 TensorFlow Lite 专注于移动和嵌入式设备,而 CoreML 则专注于苹果生态系统。在选择模型部署技术时,需要根据具体的应用场景和目标平台进行权衡。

结论

ONNX 通过打破框架孤岛来实现 AI 部署的民主化。 无论您是部署到 Kubernetes 集群还是 Raspberry Pi,导出到 ONNX 都能确保您的模型是可移植的、优化的且可用于生产的,最终实现 模型可移植性。 通过 ONNX,开发者可以专注于模型的设计和训练,而无需担心部署的复杂性,从而加速 AI 应用的落地。

下一步

  • 将您的 PyTorch/TF 模型导出到 ONNX
  • 使用 ONNX Runtime 对比原生框架的推理速度。
  • 探索量化以进行边缘部署。

资源

  • ONNX GitHub
  • ONNX Runtime Tutorials