diff --git a/doc/whats_new/v1.1.rst b/doc/whats_new/v1.1.rst index cd1102b77ed2e..471c6b86eec2d 100644 --- a/doc/whats_new/v1.1.rst +++ b/doc/whats_new/v1.1.rst @@ -258,6 +258,10 @@ Changelog Setting a transformer to "passthrough" will pass the features unchanged. :pr:`20860` by :user:`Shubhraneel Pal `. +- |Fix| :class: `pipeline.Pipeline` now does not validate hyper-parameters in + `__init__` but in `.fit()`. + :pr:`21888` by :user:`iofall ` and :user: `Arisa Y. `. + :mod:`sklearn.preprocessing` ............................ diff --git a/sklearn/pipeline.py b/sklearn/pipeline.py index 6134b6318c838..794919f6942e1 100644 --- a/sklearn/pipeline.py +++ b/sklearn/pipeline.py @@ -146,7 +146,6 @@ def __init__(self, steps, *, memory=None, verbose=False): self.steps = steps self.memory = memory self.verbose = verbose - self._validate_steps() def get_params(self, deep=True): """Get parameters for this estimator. diff --git a/sklearn/tests/test_common.py b/sklearn/tests/test_common.py index 8b0796b2b5dbc..80b9a71f853fc 100644 --- a/sklearn/tests/test_common.py +++ b/sklearn/tests/test_common.py @@ -428,7 +428,6 @@ def test_transformers_get_feature_names_out(transformer): "FeatureUnion", "GridSearchCV", "HalvingGridSearchCV", - "Pipeline", "SGDOneClassSVM", "TheilSenRegressor", "TweedieRegressor", diff --git a/sklearn/tests/test_pipeline.py b/sklearn/tests/test_pipeline.py index 77201628957e0..3a94bf10b6d3c 100644 --- a/sklearn/tests/test_pipeline.py +++ b/sklearn/tests/test_pipeline.py @@ -165,20 +165,23 @@ def predict_log_proba(self, X, got_attribute=False): return self -def test_pipeline_init(): - # Test the various init parameters of the pipeline. +def test_pipeline_invalid_parameters(): + # Test the various init parameters of the pipeline in fit + # method + pipeline = Pipeline([(1, 1)]) with pytest.raises(TypeError): - Pipeline() + pipeline.fit([[1]], [1]) - # Check that we can't instantiate pipelines with objects without fit + # Check that we can't fit pipelines with objects without fit # method msg = ( "Last step of Pipeline should implement fit " "or be the string 'passthrough'" ".*NoFit.*" ) + pipeline = Pipeline([("clf", NoFit())]) with pytest.raises(TypeError, match=msg): - Pipeline([("clf", NoFit())]) + pipeline.fit([[1]], [1]) # Smoke test with only an estimator clf = NoTrans() @@ -203,11 +206,12 @@ def test_pipeline_init(): assert pipe.named_steps["anova"] is filter1 assert pipe.named_steps["svc"] is clf - # Check that we can't instantiate with non-transformers on the way + # Check that we can't fit with non-transformers on the way # Note that NoTrans implements fit, but not transform msg = "All intermediate steps should be transformers.*\\bNoTrans\\b.*" + pipeline = Pipeline([("t", NoTrans()), ("svc", clf)]) with pytest.raises(TypeError, match=msg): - Pipeline([("t", NoTrans()), ("svc", clf)]) + pipeline.fit([[1]], [1]) # Check that params are set pipe.set_params(svc__C=0.1) @@ -1086,7 +1090,7 @@ def test_step_name_validation(): # three ways to make invalid: # - construction with pytest.raises(ValueError, match=message): - cls(**{param: bad_steps}) + cls(**{param: bad_steps}).fit([[1]], [1]) # - setattr est = cls(**{param: [("a", Mult(1))]})