在一个ONNX图中存储数组

模型转换后,将数组作为图中的常量存储并通过输出检索会很有用。这允许用户存储训练参数或其他信息,如词汇表。之前的章节展示了如何移除输出或将中间结果提升为输出。

训练和转换模型

我们从ONNX Zoo下载一个模型,但该模型也可以由其他转换器库训练和生成。

import pprint
import numpy
from onnx import load
from onnxruntime import InferenceSession
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from skl2onnx import to_onnx
from skl2onnx.helpers.onnx_helper import (
    add_output_initializer,
    select_model_inputs_outputs,
)


data = load_iris()
X, y = data.data.astype(numpy.float32), data.target
X_train, X_test, y_train, y_test = train_test_split(X, y)
model = LogisticRegression(penalty="elasticnet", C=2.0, solver="saga", l1_ratio=0.5)
model.fit(X_train, y_train)

onx = to_onnx(model, X_train[:1], target_opset=12, options={"zipmap": False})
/home/xadupre/vv/this312/lib/python3.12/site-packages/sklearn/linear_model/_sag.py:348: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge
  warnings.warn(

添加训练参数

new_onx = add_output_initializer(
    onx, ["C", "l1_ratio"], [numpy.array([model.C]), numpy.array([model.l1_ratio])]
)

推理

sess = InferenceSession(new_onx.SerializeToString(), providers=["CPUExecutionProvider"])
print("output names:", [o.name for o in sess.get_outputs()])
res = sess.run(None, {"X": X_test[:2]})
print("outputs")
pprint.pprint(res)
output names: ['label', 'probabilities', 'C', 'l1_ratio']
outputs
[array([0, 2], dtype=int64),
 array([[9.9722755e-01, 2.7724325e-03, 3.5656236e-10],
       [1.3919589e-04, 7.1695939e-02, 9.2816484e-01]], dtype=float32),
 array([2.]),
 array([0.5])]

这个方案的主要缺点是会增加预测时间,因为onnxruntime在每次预测时都会复制这些常量。可以将这些常量存储在单独的ONNX图中,或者将其移除。

选择输出

下一个函数从模型中移除不需要的输出,而不仅仅是常量。下一个模型只保留概率。

simple_onx = select_model_inputs_outputs(new_onx, ["probabilities"])

sess = InferenceSession(
    simple_onx.SerializeToString(), providers=["CPUExecutionProvider"]
)
print("output names:", [o.name for o in sess.get_outputs()])
res = sess.run(None, {"X": X_test[:2]})
print("outputs")
pprint.pprint(res)

# Function *select_model_inputs_outputs* add also promote an intermediate
# result to an output.
#
output names: ['probabilities']
outputs
[array([[9.9722755e-01, 2.7724325e-03, 3.5656236e-10],
       [1.3919589e-04, 7.1695939e-02, 9.2816484e-01]], dtype=float32)]

此示例仅在内存中使用ONNX图,从不保存或加载模型。保存或加载模型可使用以下代码片段完成。

保存模型

with open("simplified_model.onnx", "wb") as f:
    f.write(simple_onx.SerializeToString())

加载模型

model = load("simplified_model.onnx")

sess = InferenceSession(model.SerializeToString(), providers=["CPUExecutionProvider"])
print("output names:", [o.name for o in sess.get_outputs()])
res = sess.run(None, {"X": X_test[:2]})
print("outputs")
pprint.pprint(res)
output names: ['probabilities']
outputs
[array([[9.9722755e-01, 2.7724325e-03, 3.5656236e-10],
       [1.3919589e-04, 7.1695939e-02, 9.2816484e-01]], dtype=float32)]

脚本总运行时间: (0分钟 0.058秒)

由Sphinx-Gallery生成