From 015ecedc13c62a17ecda163ec38ae06ecc7b4e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?xavier=20dupr=C3=A9?= Date: Mon, 18 May 2020 12:02:36 +0200 Subject: [PATCH] refactor rewritten sklearn operators --- mlprodict/__init__.py | 2 +- .../register_rewritten_converters.py | 14 ++++ mlprodict/onnx_conv/sklconv/svm_converters.py | 57 +++++++++++++++++ .../onnx_conv/sklconv/tree_converters.py | 64 ++++++++++++------- .../onnxrt/validate/validate_scenarios.py | 4 +- 5 files changed, 115 insertions(+), 26 deletions(-) create mode 100644 mlprodict/onnx_conv/sklconv/svm_converters.py diff --git a/mlprodict/__init__.py b/mlprodict/__init__.py index 508a785eb..85f3eb450 100644 --- a/mlprodict/__init__.py +++ b/mlprodict/__init__.py @@ -4,7 +4,7 @@ @brief Ways to speed up predictions for a machine learned model. """ -__version__ = "0.3.1097" +__version__ = "0.3.1099" __author__ = "Xavier Dupré" diff --git a/mlprodict/onnx_conv/register_rewritten_converters.py b/mlprodict/onnx_conv/register_rewritten_converters.py index 639f26818..61792d21b 100644 --- a/mlprodict/onnx_conv/register_rewritten_converters.py +++ b/mlprodict/onnx_conv/register_rewritten_converters.py @@ -19,10 +19,24 @@ new_convert_sklearn_random_forest_classifier, new_convert_sklearn_random_forest_regressor, ) +from .sklconv.svm_converters import ( + new_convert_sklearn_svm_classifier, + new_convert_sklearn_svm_regressor, +) _overwritten_operators = { # + 'SklearnOneClassSVM': RegisteredConverter( + new_convert_sklearn_svm_regressor, + _converter_pool['SklearnOneClassSVM'].get_allowed_options()), + 'SklearnSVR': RegisteredConverter( + new_convert_sklearn_svm_regressor, + _converter_pool['SklearnSVR'].get_allowed_options()), + 'SklearnSVC': RegisteredConverter( + new_convert_sklearn_svm_classifier, + _converter_pool['SklearnSVC'].get_allowed_options()), + # 'SklearnDecisionTreeRegressor': RegisteredConverter( new_convert_sklearn_decision_tree_regressor, _converter_pool['SklearnDecisionTreeRegressor'].get_allowed_options()), diff --git a/mlprodict/onnx_conv/sklconv/svm_converters.py b/mlprodict/onnx_conv/sklconv/svm_converters.py new file mode 100644 index 000000000..ec1ec4d39 --- /dev/null +++ b/mlprodict/onnx_conv/sklconv/svm_converters.py @@ -0,0 +1,57 @@ +""" +@file +@brief Rewrites some of the converters implemented in +:epkg:`sklearn-onnx`. +""" +import numpy +from skl2onnx.operator_converters.support_vector_machines import ( + convert_sklearn_svm_regressor, + convert_sklearn_svm_classifier) + + +def _op_type_domain_regressor(container): + """ + Defines *op_type* and *op_domain* based on + `container.dtype`. + """ + if container.dtype == numpy.float32: + return 'SVMRegressor', 'ai.onnx.ml', 1 + if container.dtype == numpy.float64: + return 'SVMRegressorDouble', 'mlprodict', 1 + raise RuntimeError("Unsupported dtype {}.".format(container.dtype)) + + +def _op_type_domain_classifier(container): + """ + Defines *op_type* and *op_domain* based on + `container.dtype`. + """ + if container.dtype == numpy.float32: + return 'SVMClassifier', 'ai.onnx.ml', 1 + if container.dtype == numpy.float64: + return 'SVMClassifierDouble', 'mlprodict', 1 + raise RuntimeError("Unsupported dtype {}.".format(container.dtype)) + + +def new_convert_sklearn_svm_regressor(scope, operator, container): + """ + Rewrites the converters implemented in + :epkg:`sklearn-onnx` to support an operator supporting + doubles. + """ + op_type, op_domain, op_version = _op_type_domain_regressor(container) + convert_sklearn_svm_regressor( + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) + + +def new_convert_sklearn_svm_classifier(scope, operator, container): + """ + Rewrites the converters implemented in + :epkg:`sklearn-onnx` to support an operator supporting + doubles. + """ + op_type, op_domain, op_version = _op_type_domain_classifier(container) + convert_sklearn_svm_classifier( + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) diff --git a/mlprodict/onnx_conv/sklconv/tree_converters.py b/mlprodict/onnx_conv/sklconv/tree_converters.py index 0bae17995..2d9f08571 100644 --- a/mlprodict/onnx_conv/sklconv/tree_converters.py +++ b/mlprodict/onnx_conv/sklconv/tree_converters.py @@ -15,38 +15,52 @@ convert_sklearn_random_forest_regressor_converter) -def _op_type_domain(container): +def _op_type_domain_regressor(container): """ Defines *op_type* and *op_domain* based on `container.dtype`. """ if container.dtype == numpy.float32: - return 'TreeEnsembleRegressor', 'ai.onnx.ml' + return 'TreeEnsembleRegressor', 'ai.onnx.ml', 1 if container.dtype == numpy.float64: - return 'TreeEnsembleRegressorDouble', 'mlprodict' + return 'TreeEnsembleRegressorDouble', 'mlprodict', 1 raise RuntimeError("Unsupported dtype {}.".format(container.dtype)) -def new_convert_sklearn_decision_tree_regressor(scope, operator, container): +def _op_type_domain_classifier(container): + """ + Defines *op_type* and *op_domain* based on + `container.dtype`. + """ + if container.dtype == numpy.float32: + return 'TreeEnsembleClassifier', 'ai.onnx.ml', 1 + if container.dtype == numpy.float64: + return 'TreeEnsembleClassifierDouble', 'mlprodict', 1 + raise RuntimeError("Unsupported dtype {}.".format(container.dtype)) + + +def new_convert_sklearn_decision_tree_classifier(scope, operator, container): """ Rewrites the converters implemented in :epkg:`sklearn-onnx` to support an operator supporting doubles. """ - op_type, op_domain = _op_type_domain(container) - convert_sklearn_decision_tree_regressor( - scope, operator, container, op_type=op_type, op_domain=op_domain) + op_type, op_domain, op_version = _op_type_domain_classifier(container) + convert_sklearn_decision_tree_classifier( + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) -def new_convert_sklearn_decision_tree_classifier(scope, operator, container): +def new_convert_sklearn_decision_tree_regressor(scope, operator, container): """ Rewrites the converters implemented in :epkg:`sklearn-onnx` to support an operator supporting doubles. """ - op_type, op_domain = _op_type_domain(container) - convert_sklearn_decision_tree_classifier( - scope, operator, container, op_type=op_type, op_domain=op_domain) + op_type, op_domain, op_version = _op_type_domain_regressor(container) + convert_sklearn_decision_tree_regressor( + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) def new_convert_sklearn_gradient_boosting_classifier(scope, operator, container): @@ -55,9 +69,10 @@ def new_convert_sklearn_gradient_boosting_classifier(scope, operator, container) :epkg:`sklearn-onnx` to support an operator supporting doubles. """ - op_type, op_domain = _op_type_domain(container) + op_type, op_domain, op_version = _op_type_domain_classifier(container) convert_sklearn_gradient_boosting_classifier( - scope, operator, container, op_type=op_type, op_domain=op_domain) + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) def new_convert_sklearn_gradient_boosting_regressor(scope, operator, container): @@ -66,28 +81,31 @@ def new_convert_sklearn_gradient_boosting_regressor(scope, operator, container): :epkg:`sklearn-onnx` to support an operator supporting doubles. """ - op_type, op_domain = _op_type_domain(container) + op_type, op_domain, op_version = _op_type_domain_regressor(container) convert_sklearn_gradient_boosting_regressor( - scope, operator, container, op_type=op_type, op_domain=op_domain) + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) -def new_convert_sklearn_random_forest_regressor(scope, operator, container): +def new_convert_sklearn_random_forest_classifier(scope, operator, container): """ Rewrites the converters implemented in :epkg:`sklearn-onnx` to support an operator supporting doubles. """ - op_type, op_domain = _op_type_domain(container) - convert_sklearn_random_forest_regressor_converter( - scope, operator, container, op_type=op_type, op_domain=op_domain) + op_type, op_domain, op_version = _op_type_domain_classifier(container) + convert_sklearn_random_forest_classifier( + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) -def new_convert_sklearn_random_forest_classifier(scope, operator, container): +def new_convert_sklearn_random_forest_regressor(scope, operator, container): """ Rewrites the converters implemented in :epkg:`sklearn-onnx` to support an operator supporting doubles. """ - op_type, op_domain = _op_type_domain(container) - convert_sklearn_random_forest_classifier( - scope, operator, container, op_type=op_type, op_domain=op_domain) + op_type, op_domain, op_version = _op_type_domain_regressor(container) + convert_sklearn_random_forest_regressor_converter( + scope, operator, container, op_type=op_type, op_domain=op_domain, + op_version=op_version) diff --git a/mlprodict/onnxrt/validate/validate_scenarios.py b/mlprodict/onnxrt/validate/validate_scenarios.py index 4761352d2..834606891 100644 --- a/mlprodict/onnxrt/validate/validate_scenarios.py +++ b/mlprodict/onnxrt/validate/validate_scenarios.py @@ -232,11 +232,11 @@ def build_custom_scenarios(): ('box-cox', {'method': 'box-cox'}), ], RandomForestClassifier: [ - ('default', {'n_estimators': 10}, + ('default', {'n_estimators': 100}, {'conv_options': [{}, {RandomForestClassifier: {'zipmap': False}}]}), ], RandomForestRegressor: [ - ('default', {'n_estimators': 10}), + ('default', {'n_estimators': 100}), ], RandomizedSearchCV: [ ('cl', {