diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0b51164f..8e3f3826 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,15 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] python_version: ['3.12', '3.11', '3.10', '3.9'] include: + - python_version: '3.12' + documentation: 1 + numpy_version: '>=1.21.1' + scipy_version: '>=1.7.0' + onnx_version: 'onnx==1.17.0' + onnxrt_version: 'onnxruntime==1.20.1' + sklearn_version: '==1.6.0' + lgbm_version: ">=4" + xgboost_version: ">=2" - python_version: '3.12' documentation: 0 numpy_version: '>=1.21.1' @@ -19,7 +28,7 @@ jobs: lgbm_version: ">=4" xgboost_version: ">=2" - python_version: '3.11' - documentation: 1 + documentation: 0 numpy_version: '>=1.21.1' scipy_version: '>=1.7.0' onnx_version: 'onnx<1.16.0' @@ -82,13 +91,11 @@ jobs: - name: versions run: | - python -c "from numpy import __version__;print('numpy', __version__)" python -c "from pandas import __version__;print('pandas', __version__)" python -c "from scipy import __version__;print('scipy', __version__)" python -c "from sklearn import __version__;print('sklearn', __version__)" python -c "from onnxruntime import __version__;print('onnxruntime', __version__)" python -c "from onnx import __version__;print('onnx', __version__)" - python -c "from xgboost import __version__;print('xgboost', __version__)" python -c "from catboost import __version__;print('catboost', __version__)" python -c "import onnx.defs;print('onnx_opset_version', onnx.defs.onnx_opset_version())" @@ -96,6 +103,7 @@ jobs: if: matrix.os != 'macos-latest' run: | python -c "from lightgbm import __version__;print('lightgbm', __version__)" + python -c "from xgboost import __version__;print('xgboost', __version__)" - name: Run tests baseline run: pytest --maxfail=10 --durations=10 tests/baseline diff --git a/onnxmltools/convert/coreml/shape_calculators/OneHotEncoder.py b/onnxmltools/convert/coreml/shape_calculators/OneHotEncoder.py index bd3535e5..8d4accc3 100644 --- a/onnxmltools/convert/coreml/shape_calculators/OneHotEncoder.py +++ b/onnxmltools/convert/coreml/shape_calculators/OneHotEncoder.py @@ -26,7 +26,7 @@ def calculate_one_hot_encoder_output_shapes(operator): operator.outputs[0].type = FloatTensorType( [N, len(int_categories)], doc_string=operator.outputs[0].type.doc_string ) - elif len(str_categories) > 0 and type(operator.inputs[0].type) == StringTensorType: + elif len(str_categories) > 0 and type(operator.inputs[0].type) is StringTensorType: operator.outputs[0].type = FloatTensorType( [N, len(str_categories)], doc_string=operator.outputs[0].type.doc_string ) diff --git a/onnxmltools/utils/tests_helper.py b/onnxmltools/utils/tests_helper.py index 78d8eb81..c0084351 100644 --- a/onnxmltools/utils/tests_helper.py +++ b/onnxmltools/utils/tests_helper.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 +import unittest import pickle import os import numpy @@ -87,16 +88,22 @@ def dump_data_and_model( if not os.path.exists(folder): os.makedirs(folder) - if hasattr(model, "predict"): + if "LGBM" in model.__class__.__name__: try: import lightgbm except ImportError: - lightgbm = None + raise unittest.SkipTest("lightgbm cannot be imported.") + else: + lightgbm = None + if "XGB" in model.__class__.__name__ or "Booster" in model.__class__.__name__: try: import xgboost except ImportError: - xgboost = None + raise unittest.SkipTest("xgboost cannot be imported.") + else: + xgboost = None + if hasattr(model, "predict"): if lightgbm is not None and isinstance(model, lightgbm.Booster): # LightGBM Booster model_dict = model.dump_model() diff --git a/onnxmltools/utils/utils_backend_onnxruntime.py b/onnxmltools/utils/utils_backend_onnxruntime.py index edb6fea7..9076fb83 100644 --- a/onnxmltools/utils/utils_backend_onnxruntime.py +++ b/onnxmltools/utils/utils_backend_onnxruntime.py @@ -297,6 +297,30 @@ def _compare_expected( (len(expected), len(output.ravel()) // len(expected)) ) if len(expected) != len(output): + if ( + len(output) == 2 + and len(expected) == 1 + and output[0].dtype in (numpy.int64, numpy.int32) + ): + # a classifier + if len(expected[0].shape) == 1: + expected = [ + numpy.hstack( + [ + 1 - expected[0].reshape((-1, 1)), + expected[0].reshape((-1, 1)), + ] + ) + ] + return _compare_expected( + expected, + output[1:], + sess, + onnx, + decimal=5, + onnx_shape=None, + **kwargs + ) raise OnnxRuntimeAssertionError( "Unexpected number of outputs '{0}', expected={1}, got={2}".format( onnx, len(expected), len(output) diff --git a/tests/xgboost/test_xgboost_converters.py b/tests/xgboost/test_xgboost_converters.py index c364257a..7eec135c 100644 --- a/tests/xgboost/test_xgboost_converters.py +++ b/tests/xgboost/test_xgboost_converters.py @@ -8,6 +8,7 @@ import numpy as np from numpy.testing import assert_almost_equal import pandas +import packaging.version as pv from sklearn.datasets import ( load_diabetes, load_iris, @@ -16,18 +17,25 @@ make_regression, ) from sklearn.model_selection import train_test_split -from xgboost import ( - XGBRegressor, - XGBClassifier, - train, - DMatrix, - Booster, - train as train_xgb, -) + +try: + from xgboost import ( + XGBRegressor, + XGBClassifier, + train, + DMatrix, + Booster, + train as train_xgb, + ) +except Exception: + XGBRegressor = None +import sklearn from sklearn.preprocessing import StandardScaler from onnx.defs import onnx_opset_version from onnxconverter_common.onnx_ex import DEFAULT_OPSET_NUMBER -from onnxmltools.convert import convert_xgboost + +if XGBRegressor is not None: + from onnxmltools.convert import convert_xgboost from onnxmltools.convert.common.data_types import FloatTensorType from onnxmltools.utils import dump_data_and_model from onnxruntime import InferenceSession @@ -67,6 +75,7 @@ def _fit_classification_model(model, n_classes, is_str=False, dtype=None): class TestXGBoostModels(unittest.TestCase): + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_regressor(self): iris = load_diabetes() x = iris.data @@ -89,6 +98,7 @@ def test_xgb_regressor(self): basename="SklearnXGBRegressor-Dec3", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_regressor_poisson(self): iris = load_diabetes() x = iris.data @@ -116,6 +126,7 @@ def test_xgb_regressor_poisson(self): basename=f"SklearnXGBRegressorPoisson{nest}-Dec3", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb0_classifier(self): xgb, x_test = _fit_classification_model(XGBClassifier(), 2) conv_model = convert_xgboost( @@ -126,6 +137,7 @@ def test_xgb0_classifier(self): dump_data_and_model(x_test, xgb, conv_model, basename="SklearnXGBClassifier") + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_uint8(self): xgb, x_test = _fit_classification_model(XGBClassifier(), 2, dtype=np.uint8) conv_model = convert_xgboost( @@ -136,6 +148,7 @@ def test_xgb_classifier_uint8(self): dump_data_and_model(x_test, xgb, conv_model, basename="SklearnXGBClassifier") + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_multi(self): xgb, x_test = _fit_classification_model(XGBClassifier(), 3) conv_model = convert_xgboost( @@ -148,6 +161,7 @@ def test_xgb_classifier_multi(self): x_test, xgb, conv_model, basename="SklearnXGBClassifierMulti" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_multi_reglog(self): xgb, x_test = _fit_classification_model( XGBClassifier(objective="reg:logistic"), 4 @@ -162,6 +176,7 @@ def test_xgb_classifier_multi_reglog(self): x_test, xgb, conv_model, basename="SklearnXGBClassifierMultiRegLog" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_reglog(self): xgb, x_test = _fit_classification_model( XGBClassifier(objective="reg:logistic"), 2 @@ -176,6 +191,7 @@ def test_xgb_classifier_reglog(self): x_test, xgb, conv_model, basename="SklearnXGBClassifierRegLog-Dec4" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_multi_discrete_int_labels(self): iris = load_iris() x = iris.data[:, :2] @@ -198,6 +214,7 @@ def test_xgb_classifier_multi_discrete_int_labels(self): basename="SklearnXGBClassifierMultiDiscreteIntLabels", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb1_booster_classifier_bin(self): x, y = make_classification( n_classes=2, n_features=5, n_samples=100, random_state=42, n_informative=3 @@ -221,6 +238,7 @@ def test_xgb1_booster_classifier_bin(self): x_test.astype(np.float32), model, model_onnx, basename="XGBBoosterMCl" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb0_booster_classifier_multiclass_softprob(self): x, y = make_classification( n_classes=3, n_features=5, n_samples=100, random_state=42, n_informative=3 @@ -252,6 +270,7 @@ def test_xgb0_booster_classifier_multiclass_softprob(self): basename="XGBBoosterMClSoftProb", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_booster_classifier_multiclass_softmax(self): x, y = make_classification( n_classes=3, n_features=5, n_samples=100, random_state=42, n_informative=3 @@ -283,6 +302,7 @@ def test_xgboost_booster_classifier_multiclass_softmax(self): basename="XGBBoosterMClSoftMax", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_booster_reg(self): x, y = make_classification( n_classes=2, n_features=5, n_samples=100, random_state=42, n_informative=3 @@ -311,6 +331,7 @@ def test_xgboost_booster_reg(self): x_test.astype(np.float32), model, model_onnx, basename="XGBBoosterReg" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_10(self): this = os.path.abspath(os.path.dirname(__file__)) train = os.path.join(this, "input_fail_train.csv") @@ -356,12 +377,22 @@ def test_xgboost_10(self): basename="XGBBoosterRegBug", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") + @unittest.skipIf( + pv.Version(sklearn.__version__) < pv.Version("1.6.0"), + "move parameters from fit to the convstructor", + ) def test_xgboost_classifier_i5450_softmax(self): iris = load_iris() X, y = iris.data, iris.target X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=10) - clr = XGBClassifier(objective="multi:softmax", max_depth=1, n_estimators=2) - clr.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=40) + clr = XGBClassifier( + objective="multi:softmax", + max_depth=1, + n_estimators=2, + early_stopping_rounds=40, + ) + clr.fit(X_train, y_train, eval_set=[(X_test, y_test)]) initial_type = [("float_input", FloatTensorType([None, 4]))] onx = convert_xgboost( clr, initial_types=initial_type, target_opset=TARGET_OPSET @@ -382,12 +413,18 @@ def test_xgboost_classifier_i5450_softmax(self): basename="XGBClassifierIris-Out0", ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_classifier_i5450(self): iris = load_iris() X, y = iris.data, iris.target X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=10) - clr = XGBClassifier(objective="multi:softprob", max_depth=1, n_estimators=2) - clr.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=40) + clr = XGBClassifier( + objective="multi:softprob", + max_depth=1, + n_estimators=2, + early_stopping_rounds=40, + ) + clr.fit(X_train, y_train, eval_set=[(X_test, y_test)]) initial_type = [("float_input", FloatTensorType([None, 4]))] onx = convert_xgboost( clr, initial_types=initial_type, target_opset=TARGET_OPSET @@ -405,6 +442,7 @@ def test_xgboost_classifier_i5450(self): X_test.astype(np.float32) + 1e-5, clr, onx, basename="XGBClassifierIris" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_example_mnist(self): """ Train a simple xgboost model and store associated artefacts. @@ -431,6 +469,7 @@ def test_xgboost_example_mnist(self): X_test.astype(np.float32), clf, onnx_model, basename="XGBoostExample" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb0_empty_tree_classifier(self): xgb = XGBClassifier(n_estimators=2, max_depth=2) @@ -451,6 +490,7 @@ def test_xgb0_empty_tree_classifier(self): assert_almost_equal(xgb.predict_proba(X), res[1]) assert_almost_equal(xgb.predict(X), res[0]) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_best_tree_limit_classifier(self): # Train iris = load_iris() @@ -499,6 +539,7 @@ def test_xgb_best_tree_limit_classifier(self): ) assert_almost_equal(bst_loaded.predict(dtest), res[0]) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier(self): x = np.random.randn(100, 10).astype(np.float32) y = ((x.sum(axis=1) + np.random.randn(x.shape[0]) / 50 + 0.5) >= 0).astype( @@ -531,6 +572,7 @@ def test_xgb_classifier(self): res2 = oinf.run(None, {"X": x_test}) assert_almost_equal(model_skl.predict_proba(x_test), res2[1]) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_cost(self): obj_classes = { "reg:logistic": ( @@ -611,12 +653,12 @@ def test_xgb_cost(self): y = oinf.run(None, {"X": X_test.astype(np.float32)}) if cl == XGBRegressor: exp = clr.predict(X_test) - assert_almost_equal(exp, y[0].ravel(), decimal=5) + assert_almost_equal(exp, y[0].ravel(), decimal=4) else: if "softmax" not in obj: exp = clr.predict_proba(X_test) got = pandas.DataFrame(y[1]).values - assert_almost_equal(exp, got, decimal=5) + assert_almost_equal(exp, got, decimal=4) exp = clr.predict(X_test[:10]) assert_almost_equal(exp, y[0][:10]) @@ -625,6 +667,7 @@ def test_xgb_cost(self): self.assertGreater(nb_tests, 8) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_601(self): model = XGBClassifier( base_score=0.5, @@ -661,6 +704,7 @@ def test_xgb_classifier_601(self): dump_data_and_model(x_test, xgb, conv_model, basename="SklearnXGBClassifier601") + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_hinge(self): model = XGBClassifier( n_estimators=3, objective="binary:hinge", random_state=0, max_depth=2 @@ -675,6 +719,7 @@ def test_xgb_classifier_hinge(self): x_test, xgb, conv_model, basename="SklearnXGBClassifierHinge" ) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_doc_example(self): iris = load_iris() X, y = iris.data, iris.target @@ -704,6 +749,7 @@ def test_doc_example(self): pred_onx = sess.run(None, {input_name: X_test.astype(np.float32)}) assert_almost_equal(expected_prob, pred_onx[1], decimal=5) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_13(self): this = os.path.dirname(__file__) df = pandas.read_csv(os.path.join(this, "data_fail_empty.csv")) @@ -725,9 +771,10 @@ def test_xgb_classifier_13(self): colsample_bytree=0.75, random_state=42, verbosity=0, + early_stopping_rounds=40, ) - clr.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=40) + clr.fit(X_train, y_train, eval_set=[(X_test, y_test)]) initial_type = [("float_input", FloatTensorType([None, 797]))] onx = convert_xgboost( @@ -742,6 +789,7 @@ def test_xgb_classifier_13(self): assert_almost_equal(expected[1], got[1]) assert_almost_equal(expected[0], got[0]) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgb_classifier_13_2(self): this = os.path.dirname(__file__) df = pandas.read_csv(os.path.join(this, "data_bug.csv")) @@ -756,14 +804,13 @@ def test_xgb_classifier_13_2(self): "early_stopping_rounds": 113, "random_state": 42, "max_depth": 3, + "eval_metric": ["logloss", "auc", "error"], } - eval_metric = ["logloss", "auc", "error"] model = XGBClassifier(**model_param) model.fit( X=x_train, y=y_train, eval_set=[(x_test, y_test)], - eval_metric=eval_metric, verbose=False, ) @@ -787,5 +834,4 @@ def test_xgb_classifier_13_2(self): if __name__ == "__main__": - TestXGBoostModels().test_xgb_classifier_13_2() unittest.main(verbosity=2) diff --git a/tests/xgboost/test_xgboost_converters_base_score.py b/tests/xgboost/test_xgboost_converters_base_score.py index 528560d8..e719aa01 100644 --- a/tests/xgboost/test_xgboost_converters_base_score.py +++ b/tests/xgboost/test_xgboost_converters_base_score.py @@ -5,10 +5,16 @@ import scipy from numpy.testing import assert_almost_equal from sklearn.datasets import make_regression -from xgboost import XGBClassifier, XGBRegressor + +try: + from xgboost import XGBClassifier, XGBRegressor +except Exception: + XGBRegressor = None from onnx.defs import onnx_opset_version from onnxconverter_common.onnx_ex import DEFAULT_OPSET_NUMBER -from onnxmltools.convert import convert_xgboost + +if XGBRegressor is not None: + from onnxmltools.convert import convert_xgboost from onnxmltools.convert.common.data_types import FloatTensorType from onnxruntime import InferenceSession @@ -17,6 +23,7 @@ class TestXGBoostModelsBaseScore(unittest.TestCase): + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgbregressor_sparse_base_score(self): X, y = make_regression(n_samples=200, n_features=10, random_state=0) mask = np.random.randint(0, 50, size=(X.shape)) != 0 @@ -45,6 +52,7 @@ def test_xgbregressor_sparse_base_score(self): got = sess.run(None, feeds)[0] assert_almost_equal(expected, got, decimal=4) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgbregressor_sparse_no_base_score(self): X, y = make_regression(n_samples=200, n_features=10, random_state=0) mask = np.random.randint(0, 50, size=(X.shape)) != 0 @@ -73,6 +81,7 @@ def test_xgbregressor_sparse_no_base_score(self): got = sess.run(None, feeds)[0] assert_almost_equal(expected, got, decimal=4) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgbclassifier_sparse_base_score(self): X, y = make_regression(n_samples=200, n_features=10, random_state=0) mask = np.random.randint(0, 50, size=(X.shape)) != 0 @@ -102,6 +111,7 @@ def test_xgbclassifier_sparse_base_score(self): got = sess.run(None, feeds)[1] assert_almost_equal(expected.reshape((-1, 2)), got, decimal=4) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgbclassifier_sparse_no_base_score(self): X, y = make_regression(n_samples=400, n_features=10, random_state=0) mask = np.random.randint(0, 50, size=(X.shape)) != 0 diff --git a/tests/xgboost/test_xgboost_converters_rf.py b/tests/xgboost/test_xgboost_converters_rf.py index ca3ed55b..ddff9090 100644 --- a/tests/xgboost/test_xgboost_converters_rf.py +++ b/tests/xgboost/test_xgboost_converters_rf.py @@ -4,10 +4,17 @@ import numpy as np from sklearn.datasets import load_diabetes, make_classification from sklearn.model_selection import train_test_split -from xgboost import XGBRFRegressor, XGBRFClassifier + +try: + from xgboost import XGBRFRegressor, XGBRFClassifier +except Exception: + XGBRFRegressor = None + from onnx.defs import onnx_opset_version from onnxconverter_common.onnx_ex import DEFAULT_OPSET_NUMBER -from onnxmltools.convert import convert_xgboost + +if XGBRFRegressor is not None: + from onnxmltools.convert import convert_xgboost from onnxmltools.convert.common.data_types import FloatTensorType from onnxmltools.utils import dump_data_and_model @@ -46,6 +53,7 @@ def _fit_classification_model(model, n_classes, is_str=False, dtype=None): class TestXGBoostRFModels(unittest.TestCase): + @unittest.skipIf(XGBRFRegressor is None, "xgboost is not available") def test_xgbrf_aregressor(self): iris = load_diabetes() x = iris.data @@ -67,6 +75,7 @@ def test_xgbrf_aregressor(self): basename="SklearnXGBRFRegressor-Dec3", ) + @unittest.skipIf(XGBRFRegressor is None, "xgboost is not available") def test_xgbrf_classifier(self): xgb, x_test = _fit_classification_model(XGBRFClassifier(), 2) conv_model = convert_xgboost( @@ -78,5 +87,4 @@ def test_xgbrf_classifier(self): if __name__ == "__main__": - # TestXGBoostModels().test_xgboost_booster_classifier_multiclass_softprob() unittest.main(verbosity=2) diff --git a/tests/xgboost/test_xgboost_issues.py b/tests/xgboost/test_xgboost_issues.py index 47a2e08b..0c989f26 100644 --- a/tests/xgboost/test_xgboost_issues.py +++ b/tests/xgboost/test_xgboost_issues.py @@ -2,8 +2,14 @@ import unittest +try: + from xgboost import XGBRegressor +except Exception: + XGBRegressor = None + class TestXGBoostIssues(unittest.TestCase): + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_issue_676(self): import json import onnxruntime diff --git a/tests/xgboost/test_xgboost_pipeline.py b/tests/xgboost/test_xgboost_pipeline.py index 1df296f6..dc49b71b 100644 --- a/tests/xgboost/test_xgboost_pipeline.py +++ b/tests/xgboost/test_xgboost_pipeline.py @@ -10,7 +10,11 @@ from numpy.testing import assert_almost_equal import pandas import onnxruntime as rt -from xgboost import XGBRegressor + +try: + from xgboost import XGBRegressor +except Exception: + XGBRegressor = None from sklearn.model_selection import train_test_split from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline @@ -20,9 +24,11 @@ from onnxconverter_common import data_types as onnxtypes from onnxmltools.convert import convert_sklearn from onnxmltools.convert.common.data_types import FloatTensorType -from onnxmltools.convert.xgboost.operator_converters.XGBoost import ( - convert_xgboost as convert_xgb, -) + +if XGBRegressor is not None: + from onnxmltools.convert.xgboost.operator_converters.XGBoost import ( + convert_xgboost as convert_xgb, + ) try: from skl2onnx import update_registered_converter @@ -73,15 +79,18 @@ def type_for_column(column): res = [(col, type_for_column(data[col])) for col in data.columns] return res + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_10_skl_missing(self): self.common_test_xgboost_10_skl(np.nan) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_10_skl_zero(self): try: self.common_test_xgboost_10_skl(0.0, True) except RuntimeError as e: assert "Cannot convert a XGBoost model where missing values" in str(e) + @unittest.skipIf(XGBRegressor is None, "xgboost is not available") def test_xgboost_10_skl_zero_replace(self): self.common_test_xgboost_10_skl(np.nan, True) diff --git a/tests/xgboost/test_xgboost_unpickle_06.py b/tests/xgboost/test_xgboost_unpickle_06.py index 5761b551..c45258d3 100644 --- a/tests/xgboost/test_xgboost_unpickle_06.py +++ b/tests/xgboost/test_xgboost_unpickle_06.py @@ -4,10 +4,17 @@ import packaging.version as pv import unittest import pickle -import xgboost + +try: + import xgboost + from xgboost import XGBClassifier # noqa: F401 +except Exception: + xgboost = None from onnx.defs import onnx_opset_version from onnxconverter_common.onnx_ex import DEFAULT_OPSET_NUMBER -from onnxmltools.convert.xgboost import convert as convert_xgboost + +if xgboost is not None: + from onnxmltools.convert.xgboost import convert as convert_xgboost from onnxmltools.convert.common.data_types import FloatTensorType @@ -16,7 +23,7 @@ class TestXGBoostUnpickle06(unittest.TestCase): @unittest.skipIf( - pv.Version(xgboost.__version__) >= pv.Version("1.0"), + xgboost is None or pv.Version(xgboost.__version__) >= pv.Version("1.0"), reason="compatibility break with pickle in 1.0", ) def test_xgboost_unpickle_06(self):