diff --git a/doc/whats_new/v1.0.rst b/doc/whats_new/v1.0.rst index 3b3884e68e185..2d1b94498425a 100644 --- a/doc/whats_new/v1.0.rst +++ b/doc/whats_new/v1.0.rst @@ -261,6 +261,8 @@ Changelog Ridge, RidgeClassifier, RidgeCV or RidgeClassifierCV were deprecated in: :pr:`17772` by :user:`Maria Telenczuk ` and :user:`Alexandre Gramfort `. + BayesianRidge, ARDRegression were deprecated in: + :pr:`17746` by :user:`Maria Telenczuk `. - |Fix|: `sample_weight` are now fully taken into account in linear models when `normalize=True` for both feature centering and feature diff --git a/sklearn/linear_model/_bayes.py b/sklearn/linear_model/_bayes.py index 634417e2b0efa..2eae8b5c13cee 100644 --- a/sklearn/linear_model/_bayes.py +++ b/sklearn/linear_model/_bayes.py @@ -11,6 +11,7 @@ from ._base import LinearModel, _rescale_data from ..base import RegressorMixin +from ._base import _deprecate_normalize from ..utils.extmath import fast_logdet from scipy.linalg import pinvh from ..utils.validation import _check_sample_weight @@ -84,6 +85,10 @@ class BayesianRidge(RegressorMixin, LinearModel): :class:`~sklearn.preprocessing.StandardScaler` before calling ``fit`` on an estimator with ``normalize=False``. + .. deprecated:: 1.0 + ``normalize`` was deprecated in version 1.0 and will be removed in + 1.2. + copy_X : bool, default=True If True, X will be copied; else, it may be overwritten. @@ -158,7 +163,7 @@ class BayesianRidge(RegressorMixin, LinearModel): def __init__(self, *, n_iter=300, tol=1.e-3, alpha_1=1.e-6, alpha_2=1.e-6, lambda_1=1.e-6, lambda_2=1.e-6, alpha_init=None, lambda_init=None, compute_score=False, fit_intercept=True, - normalize=False, copy_X=True, verbose=False): + normalize='deprecated', copy_X=True, verbose=False): self.n_iter = n_iter self.tol = tol self.alpha_1 = alpha_1 @@ -193,6 +198,10 @@ def fit(self, X, y, sample_weight=None): ------- self : returns an instance of self. """ + self._normalize = _deprecate_normalize( + self.normalize, default=False, + estimator_name=self.__class__.__name__ + ) if self.n_iter < 1: raise ValueError('n_iter should be greater than or equal to 1.' @@ -205,7 +214,7 @@ def fit(self, X, y, sample_weight=None): dtype=X.dtype) X, y, X_offset_, y_offset_, X_scale_ = self._preprocess_data( - X, y, self.fit_intercept, self.normalize, self.copy_X, + X, y, self.fit_intercept, self._normalize, self.copy_X, sample_weight=sample_weight) if sample_weight is not None: @@ -325,7 +334,7 @@ def predict(self, X, return_std=False): if return_std is False: return y_mean else: - if self.normalize: + if self._normalize: X = (X - self.X_offset_) / self.X_scale_ sigmas_squared_data = (np.dot(X, self.sigma_) * X).sum(axis=1) y_std = np.sqrt(sigmas_squared_data + (1. / self.alpha_)) @@ -445,6 +454,10 @@ class ARDRegression(RegressorMixin, LinearModel): :class:`~sklearn.preprocessing.StandardScaler` before calling ``fit`` on an estimator with ``normalize=False``. + .. deprecated:: 1.0 + ``normalize`` was deprecated in version 1.0 and will be removed in + 1.2. + copy_X : bool, default=True If True, X will be copied; else, it may be overwritten. @@ -510,8 +523,8 @@ class ARDRegression(RegressorMixin, LinearModel): @_deprecate_positional_args def __init__(self, *, n_iter=300, tol=1.e-3, alpha_1=1.e-6, alpha_2=1.e-6, lambda_1=1.e-6, lambda_2=1.e-6, compute_score=False, - threshold_lambda=1.e+4, fit_intercept=True, normalize=False, - copy_X=True, verbose=False): + threshold_lambda=1.e+4, fit_intercept=True, + normalize='deprecated', copy_X=True, verbose=False): self.n_iter = n_iter self.tol = tol self.fit_intercept = fit_intercept @@ -543,6 +556,11 @@ def fit(self, X, y): ------- self : returns an instance of self. """ + self._normalize = _deprecate_normalize( + self.normalize, default=False, + estimator_name=self.__class__.__name__ + ) + X, y = self._validate_data(X, y, dtype=np.float64, y_numeric=True, ensure_min_samples=2) @@ -550,7 +568,7 @@ def fit(self, X, y): coef_ = np.zeros(n_features) X, y, X_offset_, y_offset_, X_scale_ = self._preprocess_data( - X, y, self.fit_intercept, self.normalize, self.copy_X) + X, y, self.fit_intercept, self._normalize, self.copy_X) self.X_offset_ = X_offset_ self.X_scale_ = X_scale_ @@ -686,7 +704,7 @@ def predict(self, X, return_std=False): if return_std is False: return y_mean else: - if self.normalize: + if self._normalize: X = (X - self.X_offset_) / self.X_scale_ X = X[:, self.lambda_ < self.threshold_lambda] sigmas_squared_data = (np.dot(X, self.sigma_) * X).sum(axis=1) diff --git a/sklearn/linear_model/tests/test_bayes.py b/sklearn/linear_model/tests/test_bayes.py index 529702ff752ac..a22a0243cdcb7 100644 --- a/sklearn/linear_model/tests/test_bayes.py +++ b/sklearn/linear_model/tests/test_bayes.py @@ -274,6 +274,8 @@ def test_update_sigma(seed): np.testing.assert_allclose(sigma, sigma_woodbury) +# FIXME: 'normalize' to be removed in 1.2 in LinearRegression +@pytest.mark.filterwarnings("ignore:'normalize' was deprecated") def test_ard_regression_predict_normalize_true(): """Check that we can predict with `normalize=True` and `return_std=True`. Non-regression test for: diff --git a/sklearn/linear_model/tests/test_common.py b/sklearn/linear_model/tests/test_common.py index 96a996d18dac7..f255384be4167 100644 --- a/sklearn/linear_model/tests/test_common.py +++ b/sklearn/linear_model/tests/test_common.py @@ -12,6 +12,8 @@ from sklearn.linear_model import RidgeCV from sklearn.linear_model import RidgeClassifier from sklearn.linear_model import RidgeClassifierCV +from sklearn.linear_model import BayesianRidge +from sklearn.linear_model import ARDRegression from sklearn.utils import check_random_state @@ -24,7 +26,8 @@ ) @pytest.mark.parametrize( "estimator", - [LinearRegression, Ridge, RidgeCV, RidgeClassifier, RidgeClassifierCV] + [LinearRegression, Ridge, RidgeCV, RidgeClassifier, RidgeClassifierCV, + BayesianRidge, ARDRegression] ) # FIXME remove test in 1.2 def test_linear_model_normalize_deprecation_message(