diff --git a/doc/whats_new/v0.24.rst b/doc/whats_new/v0.24.rst index c3f3f993a2f57..9b1ab5c78ff71 100644 --- a/doc/whats_new/v0.24.rst +++ b/doc/whats_new/v0.24.rst @@ -192,6 +192,11 @@ Changelog :class:`ensemble.GradientBoostingRegressor` and returns `1`. :pr:`17702` by :user:`Simona Maggio `. +- |API|: Mean absolute error ('mae') is now deprecated for the parameter + ``criterion`` in :class:`ensemble.GradientBoostingRegressor` and + :class:`ensemble.GradientBoostingClassifier`. + :pr:`18326` by :user:`Madhura Jayaratne `. + :mod:`sklearn.exceptions` ......................... diff --git a/sklearn/ensemble/_gb.py b/sklearn/ensemble/_gb.py index 97bdeb6e69a55..bbbe5053788e0 100644 --- a/sklearn/ensemble/_gb.py +++ b/sklearn/ensemble/_gb.py @@ -358,6 +358,10 @@ def _check_initialized(self): """Check that the estimator is initialized, raising an error if not.""" check_is_fitted(self) + @abstractmethod + def _warn_mae_for_criterion(self): + pass + def fit(self, X, y, sample_weight=None, monitor=None): """Fit the gradient boosting model. @@ -393,6 +397,10 @@ def fit(self, X, y, sample_weight=None, monitor=None): ------- self : object """ + if self.criterion == 'mae': + # TODO: This should raise an error from 0.26 + self._warn_mae_for_criterion() + # if not warmstart - clear the estimator state if not self.warm_start: self._clear_state() @@ -802,6 +810,10 @@ class GradientBoostingClassifier(ClassifierMixin, BaseGradientBoosting): some cases. .. versionadded:: 0.18 + .. deprecated:: 0.24 + `criterion='mae'` is deprecated and will be removed in version + 0.26. Use `criterion='friedman_mse'` or `'mse'` instead, as trees + should use a least-square criterion in Gradient Boosting. min_samples_split : int or float, default=2 The minimum number of samples required to split an internal node: @@ -1102,6 +1114,14 @@ def _validate_y(self, y, sample_weight): self.n_classes_ = self._n_classes return y + def _warn_mae_for_criterion(self): + # TODO: This should raise an error from 0.26 + warnings.warn("criterion='mae' was deprecated in version 0.24 and " + "will be removed in version 0.26. Use " + "criterion='friedman_mse' or 'mse' instead, as trees " + "should use a least-square criterion in Gradient " + "Boosting.", FutureWarning) + def decision_function(self, X): """Compute the decision function of ``X``. @@ -1320,6 +1340,10 @@ class GradientBoostingRegressor(RegressorMixin, BaseGradientBoosting): some cases. .. versionadded:: 0.18 + .. deprecated:: 0.24 + `criterion='mae'` is deprecated and will be removed in version + 0.26. The correct way of minimizing the absolute error is to use + `loss='lad'` instead. min_samples_split : int or float, default=2 The minimum number of samples required to split an internal node: @@ -1601,6 +1625,13 @@ def _validate_y(self, y, sample_weight=None): y = y.astype(DOUBLE) return y + def _warn_mae_for_criterion(self): + # TODO: This should raise an error from 0.26 + warnings.warn("criterion='mae' was deprecated in version 0.24 and " + "will be removed in version 0.26. The correct way of " + "minimizing the absolute error is to use loss='lad' " + "instead.", FutureWarning) + def predict(self, X): """Predict regression target for X. diff --git a/sklearn/ensemble/tests/test_gradient_boosting.py b/sklearn/ensemble/tests/test_gradient_boosting.py index 835e0c5b3bab1..812ff16933758 100644 --- a/sklearn/ensemble/tests/test_gradient_boosting.py +++ b/sklearn/ensemble/tests/test_gradient_boosting.py @@ -1333,3 +1333,17 @@ def test_attr_error_raised_if_not_fitted(): ) with pytest.raises(AttributeError, match=msg): gbr.n_classes_ + + +# TODO: Update in 0.26 to check for the error raised +@pytest.mark.parametrize('estimator', [ + GradientBoostingClassifier(criterion='mae'), + GradientBoostingRegressor(criterion='mae') +]) +def test_criterion_mae_deprecation(estimator): + # checks whether a deprecation warning is issues when criterion='mae' + # is used. + msg = ("criterion='mae' was deprecated in version 0.24 and " + "will be removed in version 0.26.") + with pytest.warns(FutureWarning, match=msg): + estimator.fit(X, y)