From b42c6e2e58f1968b0ac35f9f93d14aa798fb9096 Mon Sep 17 00:00:00 2001 From: ScottMGustafson Date: Mon, 25 Jul 2022 22:26:10 -0400 Subject: [PATCH 1/2] add fit_params to RFECV.fit --- sklearn/feature_selection/_rfe.py | 11 ++++++----- sklearn/feature_selection/tests/test_rfe.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/sklearn/feature_selection/_rfe.py b/sklearn/feature_selection/_rfe.py index 262c2757ed426..7ab7a02d9ba72 100644 --- a/sklearn/feature_selection/_rfe.py +++ b/sklearn/feature_selection/_rfe.py @@ -28,7 +28,7 @@ from ._base import _get_feature_importances -def _rfe_single_fit(rfe, estimator, X, y, train, test, scorer): +def _rfe_single_fit(rfe, estimator, X, y, train, test, scorer, **fit_params): """ Return the score for a fit across one fold. """ @@ -40,6 +40,7 @@ def _rfe_single_fit(rfe, estimator, X, y, train, test, scorer): lambda estimator, features: _score( estimator, X_test[:, features], y_test, scorer ), + **fit_params, ).scores_ @@ -645,7 +646,7 @@ def __init__( self.n_jobs = n_jobs self.min_features_to_select = min_features_to_select - def fit(self, X, y, groups=None): + def fit(self, X, y, groups=None, **fit_params): """Fit the RFE model and automatically tune the number of selected features. Parameters @@ -721,7 +722,7 @@ def fit(self, X, y, groups=None): func = delayed(_rfe_single_fit) scores = parallel( - func(rfe, self.estimator, X, y, train, test, scorer) + func(rfe, self.estimator, X, y, train, test, scorer, **fit_params) for train, test in cv.split(X, y, groups) ) @@ -742,14 +743,14 @@ def fit(self, X, y, groups=None): verbose=self.verbose, ) - rfe.fit(X, y) + rfe.fit(X, y, **fit_params) # Set final attributes self.support_ = rfe.support_ self.n_features_ = rfe.n_features_ self.ranking_ = rfe.ranking_ self.estimator_ = clone(self.estimator) - self.estimator_.fit(self._transform(X), y) + self.estimator_.fit(self._transform(X), y, **fit_params) # reverse to stay consistent with before scores_rev = scores[:, ::-1] diff --git a/sklearn/feature_selection/tests/test_rfe.py b/sklearn/feature_selection/tests/test_rfe.py index 75b84a8d2cbb1..21b46323eb5af 100644 --- a/sklearn/feature_selection/tests/test_rfe.py +++ b/sklearn/feature_selection/tests/test_rfe.py @@ -136,6 +136,21 @@ def score(self, X, y, prop=None): RFE(estimator=TestEstimator()).fit(X, y, prop="foo").score(X, y, prop="foo") +def test_RFECV_fit_params(): + """Test that RFECV passes fit_params to underlying estimator.""" + + class MockClassifierWithFitParam(MockClassifier): + def fit(self, X, y, prop=None): + if prop is None: + raise ValueError("fit: prop cannot be None") + return super().fit(X, y) + + X, y = load_iris(return_X_y=True) + with pytest.raises(ValueError, match="fit: prop cannot be None"): + RFECV(estimator=MockClassifierWithFitParam()).fit(X, y) + RFECV(estimator=MockClassifierWithFitParam()).fit(X, y, prop="foo") + + @pytest.mark.parametrize("n_features_to_select", [-1, 2.1]) def test_rfe_invalid_n_features_errors(n_features_to_select): clf = SVC(kernel="linear") From f9a60474f7b5d79389f7bf9e9a0d9de739d0707d Mon Sep 17 00:00:00 2001 From: ScottMGustafson Date: Mon, 25 Jul 2022 22:33:33 -0400 Subject: [PATCH 2/2] add fit_params to docstring --- sklearn/feature_selection/_rfe.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sklearn/feature_selection/_rfe.py b/sklearn/feature_selection/_rfe.py index 7ab7a02d9ba72..e778edb813509 100644 --- a/sklearn/feature_selection/_rfe.py +++ b/sklearn/feature_selection/_rfe.py @@ -666,6 +666,10 @@ def fit(self, X, y, groups=None, **fit_params): .. versionadded:: 0.20 + **fit_params : dict + Additional parameters passed to the `fit` method of the underlying + estimator. + Returns ------- self : object