From 8160137d95e52118f6b683e7835795f2263e5073 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:43:46 -0500 Subject: [PATCH 1/9] Mark `KNeighborsRegressor` as multi-output --- python/cuml/cuml/neighbors/kneighbors_regressor.pyx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/cuml/cuml/neighbors/kneighbors_regressor.pyx b/python/cuml/cuml/neighbors/kneighbors_regressor.pyx index 50ae13f880..dc94f4a0f4 100644 --- a/python/cuml/cuml/neighbors/kneighbors_regressor.pyx +++ b/python/cuml/cuml/neighbors/kneighbors_regressor.pyx @@ -208,6 +208,11 @@ class KNeighborsRegressor(RegressorMixin, FMajorInputTagMixin, NeighborsBase): ) self.weights = weights + def __sklearn_tags__(self): + tags = super().__sklearn_tags__() + tags.target_tags.multi_output = True + return tags + @generate_docstring() @mlfunc(set_input_type=True) def fit(self, X, y, *, convert_dtype="deprecated") -> "KNeighborsRegressor": From 86ff1f857fd6324f761678c16f112ee24de4d2a0 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:44:06 -0500 Subject: [PATCH 2/9] Fixup compat xfails --- python/cuml/tests/test_sklearn_compatibility.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index 3070aeb0f9..1819c6ab27 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -197,22 +197,22 @@ def _all_cuml_estimators(): "RandomForest uses quantile-binned splits, so sample weighting is " "not equivalent to duplicating rows" ), - "check_sample_weight_equivalence_on_sparse_data": ( - "RandomForestClassifier does not handle sparse data" - ), }, RandomForestRegressor: { - "check_regressor_data_not_an_array": "RandomForestRegressor does not handle non-array data", + "check_regressor_data_not_an_array": ( + "cuml defaults to float32 for non-arrays (while sklearn defaults to " + "float64). Our float32 and float64 results differ _just enough_ that " + "this test fails on tolerances." + ), "check_sample_weight_equivalence_on_dense_data": ( "RandomForest uses quantile-binned splits, so sample weighting is " "not equivalent to duplicating rows" ), - "check_sample_weight_equivalence_on_sparse_data": ( - "RandomForestRegressor does not handle sparse data" - ), }, KNeighborsRegressor: { - "check_supervised_y_2d": "KNeighborsRegressor does not handle 2D y", + "check_regressor_multioutput": ( + "predict returns float32 output, but the test expects float64" + ), }, LinearSVC: { "check_sample_weight_equivalence_on_dense_data": "LinearSVC sample weight equivalence not implemented", From 3add3edb2c3ff26363841e03d5b9b5817d6c915b Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:46:29 -0500 Subject: [PATCH 3/9] Update xfail reasons to be more correct --- .../cuml/tests/test_sklearn_compatibility.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index 1819c6ab27..cd5fe748d5 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -182,11 +182,11 @@ def _all_cuml_estimators(): XFAILS = { KMeans: { - "check_sample_weight_equivalence_on_dense_data": "KMeans sample weight equivalence not implemented", + "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", }, LogisticRegression: { - "check_sample_weight_equivalence_on_dense_data": "LogisticRegression sample weight equivalence not implemented", - "check_sample_weight_equivalence_on_sparse_data": "LogisticRegression does not handle sparse data", + "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", + "check_sample_weight_equivalence_on_sparse_data": "Sample weights not equal to repeating data", "check_class_weight_classifiers": "LogisticRegression does not handle class weights properly", }, Ridge: { @@ -215,18 +215,18 @@ def _all_cuml_estimators(): ), }, LinearSVC: { - "check_sample_weight_equivalence_on_dense_data": "LinearSVC sample weight equivalence not implemented", + "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", }, LinearSVR: { - "check_sample_weight_equivalence_on_dense_data": "LinearSVR sample weight equivalence not implemented", + "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", }, SVC: { - "check_sample_weight_equivalence_on_dense_data": "SVC sample weight equivalence not implemented", - "check_sample_weight_equivalence_on_sparse_data": "SVC does not handle sparse data", + "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", + "check_sample_weight_equivalence_on_sparse_data": "Sample weights not equal to repeating data", }, SVR: { - "check_sample_weight_equivalence_on_dense_data": "SVR sample weight equivalence not implemented", - "check_sample_weight_equivalence_on_sparse_data": "SVR does not handle sparse data", + "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", + "check_sample_weight_equivalence_on_sparse_data": "Sample weights not equal to repeating data", }, PCA: { "check_fit2d_1sample": "PCA does not handle single sample", @@ -253,10 +253,10 @@ def _all_cuml_estimators(): "check_transformer_preserve_dtypes": "UMAP returns float32 embeddings", }, Lasso: { - "check_sample_weight_equivalence_on_sparse_data": "Lasso QN solver has issues with sample weights", + "check_sample_weight_equivalence_on_sparse_data": "Sample weights not equal to repeating data", }, ElasticNet: { - "check_sample_weight_equivalence_on_sparse_data": "ElasticNet QN solver has issues with sample weights", + "check_sample_weight_equivalence_on_sparse_data": "Sample weights not equal to repeating data", }, StandardScaler: { "check_no_attributes_set_in_init": "Vendored __init__ sets copy/with_mean/with_std as attributes", From 6d18972fbaa93bafcc9693ecf848c8dba427dffb Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:50:28 -0500 Subject: [PATCH 4/9] Fix `TruncatedSVD` min samples/features --- python/cuml/cuml/decomposition/tsvd.pyx | 2 ++ .../cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml | 2 -- python/cuml/tests/test_sklearn_compatibility.py | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/python/cuml/cuml/decomposition/tsvd.pyx b/python/cuml/cuml/decomposition/tsvd.pyx index 8fc66e26ae..ddfffccab6 100644 --- a/python/cuml/cuml/decomposition/tsvd.pyx +++ b/python/cuml/cuml/decomposition/tsvd.pyx @@ -313,6 +313,8 @@ class TruncatedSVD(InteropMixin, dtype=("float32", "float64"), convert_dtype=convert_dtype, order="F", + ensure_min_samples=2, + ensure_min_features=2, return_index=True, reset=True, ) diff --git a/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml b/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml index 028d6c7070..6a7829f220 100644 --- a/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml +++ b/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml @@ -817,8 +817,6 @@ - "sklearn.tests.test_common::test_estimators[PCA()-check_fit2d_1sample]" - "sklearn.tests.test_common::test_estimators[RandomForestClassifier()-check_classifiers_multilabel_output_format_decision_function]" - "sklearn.tests.test_common::test_estimators[RandomForestRegressor()-check_regressor_data_not_an_array]" - - "sklearn.tests.test_common::test_estimators[TruncatedSVD()-check_fit2d_1feature]" - - "sklearn.tests.test_common::test_estimators[TruncatedSVD()-check_fit2d_1sample]" - reason: test_estimators checks fail marker: cuml_accel_test_estimators strict: false diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index cd5fe748d5..f5b0250bbf 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -232,10 +232,6 @@ def _all_cuml_estimators(): "check_fit2d_1sample": "PCA does not handle single sample", "check_fit2d_1feature": "PCA does not handle single feature", }, - TruncatedSVD: { - "check_fit2d_1sample": "TruncatedSVD does not handle single sample", - "check_fit2d_1feature": "TruncatedSVD does not handle single feature", - }, TSNE: { "check_dont_overwrite_parameters": "TSNE only supports n_components = 2", "check_pipeline_consistency": "TSNE results are not deterministic", From 41886addee03d4ab7ca1a3ceb21f8775eec1ec38 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:53:41 -0500 Subject: [PATCH 5/9] Fix `PCA` min samples/features --- python/cuml/cuml/decomposition/pca.pyx | 2 ++ .../cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml | 2 -- python/cuml/tests/test_sklearn_compatibility.py | 4 ---- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/python/cuml/cuml/decomposition/pca.pyx b/python/cuml/cuml/decomposition/pca.pyx index ae316504de..5118fda13e 100644 --- a/python/cuml/cuml/decomposition/pca.pyx +++ b/python/cuml/cuml/decomposition/pca.pyx @@ -479,6 +479,8 @@ class PCA(InteropMixin, accept_large_sparse=True, dtype=("float32", "float64"), convert_dtype=convert_dtype, + ensure_min_samples=2, + ensure_min_features=2, order="F", reset=True, ) diff --git a/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml b/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml index 6a7829f220..97c71e4234 100644 --- a/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml +++ b/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml @@ -813,8 +813,6 @@ marker: cuml_accel_test_estimators tests: - "sklearn.tests.test_common::test_estimators[KNeighborsRegressor()-check_supervised_y_no_nan]" - - "sklearn.tests.test_common::test_estimators[PCA()-check_fit2d_1feature]" - - "sklearn.tests.test_common::test_estimators[PCA()-check_fit2d_1sample]" - "sklearn.tests.test_common::test_estimators[RandomForestClassifier()-check_classifiers_multilabel_output_format_decision_function]" - "sklearn.tests.test_common::test_estimators[RandomForestRegressor()-check_regressor_data_not_an_array]" - reason: test_estimators checks fail diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index f5b0250bbf..cc5018309d 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -228,10 +228,6 @@ def _all_cuml_estimators(): "check_sample_weight_equivalence_on_dense_data": "Sample weights not equal to repeating data", "check_sample_weight_equivalence_on_sparse_data": "Sample weights not equal to repeating data", }, - PCA: { - "check_fit2d_1sample": "PCA does not handle single sample", - "check_fit2d_1feature": "PCA does not handle single feature", - }, TSNE: { "check_dont_overwrite_parameters": "TSNE only supports n_components = 2", "check_pipeline_consistency": "TSNE results are not deterministic", From 8692c3c9d13fdbec729f5465f257279135a40e8a Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:56:29 -0500 Subject: [PATCH 6/9] Fix TSNE min samples/features --- python/cuml/cuml/manifold/t_sne.pyx | 2 ++ python/cuml/tests/test_sklearn_compatibility.py | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/cuml/cuml/manifold/t_sne.pyx b/python/cuml/cuml/manifold/t_sne.pyx index 7e9dccd929..656c3d54cc 100644 --- a/python/cuml/cuml/manifold/t_sne.pyx +++ b/python/cuml/cuml/manifold/t_sne.pyx @@ -595,6 +595,8 @@ class TSNE(InteropMixin, convert_dtype=convert_dtype, order="F", accept_sparse="csr", + ensure_min_samples=2, + ensure_min_features=2, reset=True, return_index=True, ) diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index cc5018309d..dc80a293cc 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -233,8 +233,6 @@ def _all_cuml_estimators(): "check_pipeline_consistency": "TSNE results are not deterministic", "check_methods_sample_order_invariance": "TSNE results depend on sample order", "check_methods_subset_invariance": "TSNE results depend on data subset", - "check_fit2d_1sample": "TSNE does not handle single sample", - "check_fit2d_1feature": "TSNE does not handle single feature", "check_fit2d_predict1d": "TSNE only supports n_components = 2", }, UMAP: { From da19b49e54f8b244a4b596d68129ae00dcfd33c1 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 13:59:20 -0500 Subject: [PATCH 7/9] Update one more xfail reason --- python/cuml/tests/test_sklearn_compatibility.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index dc80a293cc..186822bdc4 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -236,7 +236,11 @@ def _all_cuml_estimators(): "check_fit2d_predict1d": "TSNE only supports n_components = 2", }, UMAP: { - "check_transformer_data_not_an_array": "UMAP does not handle non-array data", + "check_transformer_data_not_an_array": ( + "cuml defaults to float32 for non-arrays (while sklearn defaults to " + "float64). Our float32 and float64 results differ _just enough_ that " + "this test fails on tolerances." + ), "check_methods_sample_order_invariance": "UMAP results depend on sample order", "check_transformer_general": "UMAP does not have consistent fit_transform and transform outputs", "check_methods_subset_invariance": "UMAP results depend on data subset", From ddabacc0305a76cc93e6638d9ad2a16457ef9773 Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Fri, 10 Jul 2026 14:10:27 -0500 Subject: [PATCH 8/9] Fixup StandardScaler --- .../cuml/cuml/_thirdparty/sklearn/preprocessing/_data.py | 9 ++++----- python/cuml/tests/test_sklearn_compatibility.py | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/python/cuml/cuml/_thirdparty/sklearn/preprocessing/_data.py b/python/cuml/cuml/_thirdparty/sklearn/preprocessing/_data.py index 061b8b3d58..a042bb225c 100644 --- a/python/cuml/cuml/_thirdparty/sklearn/preprocessing/_data.py +++ b/python/cuml/cuml/_thirdparty/sklearn/preprocessing/_data.py @@ -24,7 +24,6 @@ # This code is under BSD 3 clause license. # Authors mentioned above do not endorse or promote this production. -import numbers import warnings from itertools import chain, combinations from itertools import combinations_with_replacement as combinations_w_r @@ -772,10 +771,10 @@ def partial_fit(self, X, y=None) -> "StandardScaler": # if n_samples_seen_ is an integer (i.e. no missing values), we need to # transform it to a NumPy array of shape (n_features,) required by # incr_mean_variance_axis and _incremental_variance_axis - if (hasattr(self, 'n_samples_seen_') and - isinstance(self.n_samples_seen_, numbers.Integral)): - self.n_samples_seen_ = np.repeat( - self.n_samples_seen_, X.shape[1]).astype(np.int64, copy=False) + if hasattr(self, 'n_samples_seen_') and np.isscalar(self.n_samples_seen_): + self.n_samples_seen_ = np.full( + X.shape[1], self.n_samples_seen_, dtype="int64" + ) if sparse.issparse(X): if self.with_mean: diff --git a/python/cuml/tests/test_sklearn_compatibility.py b/python/cuml/tests/test_sklearn_compatibility.py index 186822bdc4..06aaa8c613 100644 --- a/python/cuml/tests/test_sklearn_compatibility.py +++ b/python/cuml/tests/test_sklearn_compatibility.py @@ -254,7 +254,6 @@ def _all_cuml_estimators(): }, StandardScaler: { "check_no_attributes_set_in_init": "Vendored __init__ sets copy/with_mean/with_std as attributes", - "check_fit_score_takes_y": "AttributeError: 'int' object has no attribute 'repeat'", "check_do_not_raise_errors_in_init_or_set_params": "StandardScaler(**params) raises an exception", }, } From 5488e644c5d482932643d053600a39d371be317b Mon Sep 17 00:00:00 2001 From: Jim Crist-Harif Date: Sun, 12 Jul 2026 22:48:00 -0500 Subject: [PATCH 9/9] One more passing xfail --- .../cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml b/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml index 97c71e4234..0d49c7e4f0 100644 --- a/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml +++ b/python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-list.yaml @@ -183,7 +183,6 @@ - "sklearn.linear_model.tests.test_sparse_coordinate_descent::test_sparse_dense_equality[csc_matrix-True-6-24-True-ElasticNet]" - "sklearn.linear_model.tests.test_sparse_coordinate_descent::test_sparse_dense_equality[csc_matrix-True-6-24-True-Lasso]" - "sklearn.utils.tests.test_estimator_checks::test_check_estimator" - - "sklearn.utils.tests.test_estimator_checks::test_check_estimator_clones" - reason: Test should fail with cuml.accel marker: cuml_accel_bugs tests: