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/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/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/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/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": 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..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: @@ -813,12 +812,8 @@ 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]" - - "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 3070aeb0f9..06aaa8c613 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: { @@ -197,70 +197,63 @@ 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", + "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", - }, - PCA: { - "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", + "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", }, TSNE: { "check_dont_overwrite_parameters": "TSNE only supports n_components = 2", "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: { - "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", "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", - "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", }, }