转换时将算子列入黑名单

有些运行时并未实现 ONNX 中所有可用算子的运行时。转换器对此不知情,但可以将某些算子列入黑名单。大多数转换器不会改变其行为,如果使用黑名单中的算子则会失败;有少数转换器会生成不同的 ONNX 图。

高斯混合模型 (GaussianMixture)

第一个根据算子黑名单改变其行为的转换器是针对模型 GaussianMixture 的。

from timeit import timeit
import numpy
from onnxruntime import InferenceSession
from sklearn.mixture import GaussianMixture
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from skl2onnx import to_onnx

data = load_iris()
X_train, X_test = train_test_split(data.data)
model = GaussianMixture()
model.fit(X_train)
GaussianMixture()
在 Jupyter 环境中,请重新运行此单元格以显示 HTML 表示或信任该 Notebook。
在 GitHub 上,HTML 表示无法渲染,请尝试使用 nbviewer.org 加载此页面。


默认转换

model_onnx = to_onnx(
    model,
    X_train[:1].astype(numpy.float32),
    options={id(model): {"score_samples": True}},
    target_opset=12,
)
sess = InferenceSession(
    model_onnx.SerializeToString(), providers=["CPUExecutionProvider"]
)

xt = X_test[:5].astype(numpy.float32)
print(model.score_samples(xt))
print(sess.run(None, {"X": xt})[2])
[-1.90576222 -0.96229758 -2.40249961 -4.2508906  -5.73341576]
[[-1.9057629]
 [-0.9622972]
 [-2.4025004]
 [-4.2508907]
 [-5.7334156]]

不使用 ReduceLogSumExp 的转换

参数 black_op 用于告诉转换器不要使用此算子。让我们看看在这种情况下转换器会产生什么。

model_onnx2 = to_onnx(
    model,
    X_train[:1].astype(numpy.float32),
    options={id(model): {"score_samples": True}},
    black_op={"ReduceLogSumExp"},
    target_opset=12,
)
sess2 = InferenceSession(
    model_onnx2.SerializeToString(), providers=["CPUExecutionProvider"]
)

xt = X_test[:5].astype(numpy.float32)
print(model.score_samples(xt))
print(sess2.run(None, {"X": xt})[2])
[-1.90576222 -0.96229758 -2.40249961 -4.2508906  -5.73341576]
[[-1.9057629]
 [-0.9622972]
 [-2.4025004]
 [-4.2508907]
 [-5.7334156]]

处理时间

print(
    timeit(
        stmt="sess.run(None, {'X': xt})", number=10000, globals={"sess": sess, "xt": xt}
    )
)

print(
    timeit(
        stmt="sess2.run(None, {'X': xt})",
        number=10000,
        globals={"sess2": sess2, "xt": xt},
    )
)
0.22418856500007678
0.28478742000152124

使用 ReduceLogSumExp 的模型要快得多。

如果转换器无法在不使用…的情况下转换

许多转换器不考虑算子的白名单和黑名单。如果转换器在不使用黑名单中的算子(或仅使用白名单中的算子)的情况下无法完成转换,则 skl2onnx 会引发错误。

try:
    to_onnx(
        model,
        X_train[:1].astype(numpy.float32),
        options={id(model): {"score_samples": True}},
        black_op={"ReduceLogSumExp", "Add"},
        target_opset=12,
    )
except RuntimeError as e:
    print("Error:", e)
Error: Operator 'Add' is black listed.

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

由 Sphinx-Gallery 生成的画廊