From ba167b384b90aba7246e23124da8ce07b357aec8 Mon Sep 17 00:00:00 2001 From: adrinjalali Date: Fri, 5 May 2023 14:18:19 +0200 Subject: [PATCH 1/5] FIX fix available_if for MultiOutputRegressor.partial_fit --- sklearn/multioutput.py | 19 +++++++++++++++---- sklearn/tests/test_multioutput.py | 9 +++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sklearn/multioutput.py b/sklearn/multioutput.py index cf49f82245c09..97198d3f29953 100644 --- a/sklearn/multioutput.py +++ b/sklearn/multioutput.py @@ -70,15 +70,26 @@ def _partial_fit_estimator( def _available_if_estimator_has(attr): - """Return a function to check if `estimator` or `estimators_` has `attr`. + """Return a function to check if the sub-estimator(s) has(have) `attr`. Helper for Chain implementations. """ def _check(self): - return hasattr(self.estimator, attr) or all( - hasattr(est, attr) for est in self.estimators_ - ) + if hasattr(self, "estimator"): + estimator = ( + self.estimator_ if hasattr(self, "estimator_") else self.estimator + ) + if hasattr(estimator, attr): + return True + + if hasattr(self, "estimators"): + estimators = ( + self.estimators_ if hasattr(self, "estimators_") else self.estimators + ) + return all(hasattr(est, attr) for est in estimators) + + return False return available_if(_check) diff --git a/sklearn/tests/test_multioutput.py b/sklearn/tests/test_multioutput.py index 371c516f197c5..7761fb0ad1325 100644 --- a/sklearn/tests/test_multioutput.py +++ b/sklearn/tests/test_multioutput.py @@ -766,3 +766,12 @@ def test_multioutputregressor_ducktypes_fitted_estimator(): # Does not raise reg.predict(X) + + +def test_multioutput_regressor_has_partial_fit(): + # Test that an unfitted MultiOutputRegressor handles available_if for + # partial_fit correctly + est = MultiOutputRegressor(LinearRegression()) + msg = "This 'MultiOutputRegressor' has no attribute 'partial_fit'" + with pytest.raises(AttributeError, match=msg): + getattr(est, "partial_fit") From df986b6043e60f1cadf82be5ba62c97ea1f68245 Mon Sep 17 00:00:00 2001 From: adrinjalali Date: Fri, 5 May 2023 14:23:39 +0200 Subject: [PATCH 2/5] add changelog --- doc/whats_new/v1.3.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/whats_new/v1.3.rst b/doc/whats_new/v1.3.rst index 12f50ca7fc2b5..8d818cbede836 100644 --- a/doc/whats_new/v1.3.rst +++ b/doc/whats_new/v1.3.rst @@ -418,6 +418,14 @@ Changelog `return_indices` to return the train-test indices of each cv split. :pr:`25659` by :user:`Guillaume Lemaitre `. +:mod:`sklearn.multioutput` +......................... + +- |Fix| :func:`getattr` on :meth:`multioutput.MultiOutputRegressor.partial_fit` + and :meth:`multioutput.MultiOutputClassifier.partial_fit` now correctly raise + an `AttributeError` if done before calling `fit`. :pr:`26333` by `Adrin + Jalali`_. + :mod:`sklearn.naive_bayes` .......................... From aeee9794f299f0a0c45c4968da507c8445ca39b9 Mon Sep 17 00:00:00 2001 From: adrinjalali Date: Fri, 5 May 2023 15:05:41 +0200 Subject: [PATCH 3/5] fix title underline --- doc/whats_new/v1.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats_new/v1.3.rst b/doc/whats_new/v1.3.rst index 8d818cbede836..99671d49752b4 100644 --- a/doc/whats_new/v1.3.rst +++ b/doc/whats_new/v1.3.rst @@ -419,7 +419,7 @@ Changelog :pr:`25659` by :user:`Guillaume Lemaitre `. :mod:`sklearn.multioutput` -......................... +.......................... - |Fix| :func:`getattr` on :meth:`multioutput.MultiOutputRegressor.partial_fit` and :meth:`multioutput.MultiOutputClassifier.partial_fit` now correctly raise From f6855c4ad2a6c1e02eca54556a096545a1df792f Mon Sep 17 00:00:00 2001 From: adrinjalali Date: Fri, 5 May 2023 15:18:06 +0200 Subject: [PATCH 4/5] simplify --- sklearn/multioutput.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/sklearn/multioutput.py b/sklearn/multioutput.py index 97198d3f29953..bbb61275342e0 100644 --- a/sklearn/multioutput.py +++ b/sklearn/multioutput.py @@ -76,18 +76,11 @@ def _available_if_estimator_has(attr): """ def _check(self): - if hasattr(self, "estimator"): - estimator = ( - self.estimator_ if hasattr(self, "estimator_") else self.estimator - ) - if hasattr(estimator, attr): - return True + if hasattr(self.estimator, attr): + return True - if hasattr(self, "estimators"): - estimators = ( - self.estimators_ if hasattr(self, "estimators_") else self.estimators - ) - return all(hasattr(est, attr) for est in estimators) + if hasattr(self, "estimators_"): + return all(hasattr(est, attr) for est in self.estimators_) return False From 932606f49574f298268c243e0fec6fbe04520354 Mon Sep 17 00:00:00 2001 From: Adrin Jalali Date: Fri, 5 May 2023 15:33:10 +0200 Subject: [PATCH 5/5] Update sklearn/multioutput.py Co-authored-by: Guillaume Lemaitre --- sklearn/multioutput.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sklearn/multioutput.py b/sklearn/multioutput.py index bbb61275342e0..b26b0fd0cdcdc 100644 --- a/sklearn/multioutput.py +++ b/sklearn/multioutput.py @@ -76,12 +76,12 @@ def _available_if_estimator_has(attr): """ def _check(self): - if hasattr(self.estimator, attr): - return True - if hasattr(self, "estimators_"): return all(hasattr(est, attr) for est in self.estimators_) + if hasattr(self.estimator, attr): + return True + return False return available_if(_check)