ONNX 格式转换#

在生产中使用 ONNX 意味着模型的预测函数可以用 ONNX 算子实现。必须选择一个运行时,该运行时在模型部署的平台上可用。检查差异并最终测量延迟。如果存在一个支持模型所有部分的转换库,则模型转换的第一步可能很容易。如果不是这种情况,必须在 ONNX 中实现缺失的部分。这可能会非常耗时。

ONNX 转换库#

机器学习库通常有自己独特的设计。这就是为什么每个库都有一个特定的转换库。许多转换库在以下链接列出:

ONNX 转换的替代方案#

实现 ONNX 导出功能的一种替代方法是利用标准协议,如 Array API 标准,该标准规范了一组通用的数组算子。它使得代码可以在诸如 NumPy、JAX、PyTorch、CuPy 等库之间重用。ndonnx 支持使用 ONNX 后端进行执行,并为符合 Array API 标准的代码提供即时 ONNX 导出。这减少了专用转换库代码的需求,因为用于实现大部分库的相同代码可以在 ONNX 转换中重用。它还为寻找类似 NumPy 体验的转换作者提供了一种方便的原始操作,用于构建 ONNX 计算图。

ONNX 从经验中学到的技巧#

ONNX 是强类型的,并针对深度学习中最常见的类型 float32 进行了优化。标准机器学习库同时使用 float32 和 float64。numpy 通常转换为最通用的类型,即 float64。当预测函数是连续的时,这没有显著影响。当不是连续的时,必须使用正确的类型。切换到 float 时遇到的问题提供了有关该主题的更多见解。

并行化改变了计算的顺序。这通常并不重要,但它可以解释一些奇怪的差异。1 + 1e17 - 1e17 = 0,但 1e17 - 1e17 + 1 = 1。高数量级的情况虽然少见,但当模型使用矩阵的逆时并不罕见。

1 + 1e17 - 1e17
0.0
1e17 - 1e17 + 1
1.0

规避上述错误,可以:

from decimal import Decimal

a = Decimal('1')
b = Decimal('1e17')
c = Decimal('-1e17')

result = a + b + c
print(result)
1
1e17 / (1 << 32)
23283064.365386963
1e17 / (1 << 64)
0.005421010862427522