Skip to content

Commit

Permalink
FIX property for predict_proba in MultiOutput Classifier (scikit-lear…
Browse files Browse the repository at this point in the history
  • Loading branch information
rebekahkim authored and jnothman committed Nov 7, 2019
1 parent faaeba4 commit 981fa7b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
4 changes: 4 additions & 0 deletions doc/whats_new/v0.22.rst
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,10 @@ Changelog
- |Fix| :class:`multioutput.MultiOutputClassifier` now has attribute
``classes_``. :pr:`14629` by :user:`Agamemnon Krasoulis <agamemnonc>`.

- |Fix| :class:`multioutput.MultiOutputClassifier` now has `predict_proba`
as property and can be checked with `hasattr`.
:issue:`15488` :pr:`15490` by :user:`Rebekah Kim <rebekahkim>`

:mod:`sklearn.naive_bayes`
...............................

Expand Down
9 changes: 6 additions & 3 deletions sklearn/multioutput.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ def fit(self, X, Y, sample_weight=None):
self.classes_ = [estimator.classes_ for estimator in self.estimators_]
return self

def predict_proba(self, X):
@property
def predict_proba(self):
"""Probability estimates.
Returns prediction probabilities for each class of each output.
Expand All @@ -382,9 +383,11 @@ def predict_proba(self, X):
check_is_fitted(self)
if not all([hasattr(estimator, "predict_proba")
for estimator in self.estimators_]):
raise ValueError("The base estimator should implement "
"predict_proba method")
raise AttributeError("The base estimator should "
"implement predict_proba method")
return self._predict_proba

def _predict_proba(self, X):
results = [estimator.predict_proba(X) for estimator in
self.estimators_]
return results
Expand Down
21 changes: 19 additions & 2 deletions sklearn/tests/test_multioutput.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,22 @@ def test_multi_output_classification_partial_fit_parallelism():
assert est1 is not est2


# check multioutput has predict_proba
def test_hasattr_multi_output_predict_proba():
# default SGDClassifier has loss='hinge'
# which does not expose a predict_proba method
sgd_linear_clf = SGDClassifier(random_state=1, max_iter=5)
multi_target_linear = MultiOutputClassifier(sgd_linear_clf)
multi_target_linear.fit(X, y)
assert not hasattr(multi_target_linear, "predict_proba")

# case where predict_proba attribute exists
sgd_linear_clf = SGDClassifier(loss='log', random_state=1, max_iter=5)
multi_target_linear = MultiOutputClassifier(sgd_linear_clf)
multi_target_linear.fit(X, y)
assert hasattr(multi_target_linear, "predict_proba")


# check predict_proba passes
def test_multi_output_predict_proba():
sgd_linear_clf = SGDClassifier(random_state=1, max_iter=5)
Expand All @@ -199,7 +215,7 @@ def custom_scorer(estimator, X, y):
multi_target_linear = MultiOutputClassifier(sgd_linear_clf)
multi_target_linear.fit(X, y)
err_msg = "The base estimator should implement predict_proba method"
with pytest.raises(ValueError, match=err_msg):
with pytest.raises(AttributeError, match=err_msg):
multi_target_linear.predict_proba(X)


Expand Down Expand Up @@ -378,7 +394,8 @@ def test_multi_output_exceptions():
# and predict_proba are called
moc = MultiOutputClassifier(LinearSVC(random_state=0))
assert_raises(NotFittedError, moc.predict, y)
assert_raises(NotFittedError, moc.predict_proba, y)
with pytest.raises(NotFittedError):
moc.predict_proba
assert_raises(NotFittedError, moc.score, X, y)
# ValueError when number of outputs is different
# for fit and score
Expand Down

0 comments on commit 981fa7b

Please sign in to comment.