ONNX简介
开放神经网络交换ONNX(Open Neural Network Exchange)是一套表示深度神经网络模型的开放格式,由微软和Facebook于2017推出,然后迅速得到了各大厂商和框架的支持。通过短短几年的发展,已经成为表示深度学习模型的实际标准,并且通过ONNX-ML
,可以支持传统非神经网络机器学习模型,大有一统整个AI模型交换标准。
ONNX定义了一组与环境和平台无关的标准格式,为AI模型的互操作性提供了基础,使AI模型可以在不同框架和环境下交互使用。硬件和软件厂商可以基于ONNX标准优化模型性能,让所有兼容ONNX标准的框架受益。目前,ONNX主要关注在模型预测方面(inferring),使用不同框架训练的模型,转化为ONNX格式后,可以很容易的部署在兼容ONNX的运行环境中。
ONNX标准介绍
ONNX规范由以下几个部分组成:
- 一个可扩展的计算图模型:定义了通用的计算图中间表示法(Intermediate Representation)。
- 内置操作符集:
ai.onnx
和ai.onnx.ml
,ai.onnx
是默认的操作符集,主要针对神经网络模型,ai.onnx.ml
主要适用于传统非神经网络机器学习模型。 - 标准数据类型。包括张量(tensors)、序列(sequences)和映射(maps)。
目前,ONNX规范有两个官方变体,主要区别在与支持的类型和默认的操作符集。ONNX神经网络变体只使用张量作为输入和输出;而作为支持传统机器学习模型的ONNX-ML
,还可以识别序列和映射,ONNX-ML
为支持非神经网络算法扩展了ONNX操作符集。
ONNX使用protobuf序列化AI模型,顶层是一个模型(Model)结构,主要由关联的元数据和一个图(Graph)组成;图由元数据、模型参数、输入输出、和计算节点(Node
)序列组成,这些节点构成了一个计算无环图,每一个计算节点代表了一次操作符的调用,主要由节点名称、操作符、输入列表、输出列表和属性列表组成,属性列表主要记录了一些运行时常量,比如模型训练时生成的系数值。
为了更直观的了解ONNX格式内容,下面,我们训练一个简单的Logistic Regression模型,然后导出ONNX。仍然使用常用的分类数据集iris
:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
iris = load_iris()
X, y = iris.data, iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y)
clr = LogisticRegression()
clr.fit(X_train, y_train)
使用skl2onnx
把Scikit-learn模型序列化为ONNX格式:
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType
initial_type = [('float_input', FloatTensorType([1, 4]))]
onx = convert_sklearn(clr, initial_types=initial_type)
with open("logreg_iris.onnx", "wb") as f:
f.write(onx.SerializeToString())
使用ONNX Python API查看和验证模型:
import onnx
model = onnx.load('logreg_iris.onnx')
print(model)
输出模型信息如下:
我们可以看到顶层字段记录了一些模型的元数据信息,代表的含义都比较直观,字段详细解释可以参考文档 Open Neural Network Exchange - ONNX。opset_import
记录了该模型引入的操作符集。空的domain
操作符集表示引入ONNX默认的操作符集ai.onnx
。ai.onnx.ml
代表支持传统非神经网络模型操作符集,比如以上模型中的LinearClassifier
、Normalizer
和ZipMap
。图(graph)中定义了以下元素:
- 四个计算节点(node)。
- 一个输入变量
float_input
,类型为1*4的张量,elem_type
是一个DataType枚举型变量,1代表FLOAT。 - 两个输出变量
output_label
和output_probability
,output_label
类型为维数为1的INT64(elem_type: 7)张量,代表预测目标分类;output_probability
类型是映射的序列,映射的键是INT64(key_type: 7),值为维数为1的FLOAT,代表每一个目标分类的概率。
可以使用netron,图像化显示ONNX模型的计算拓扑图,以上模型如下图:
下面我们使用ONNX Runtime Python API预测该ONNX模型,当前仅使用了