Skip to content

Commit 04e0f32

Browse files
committed
MAINT threshold -> threshold_ with deprecation warning.
TST Check specifically for NotFittedError
1 parent 25db1ac commit 04e0f32

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

sklearn/covariance/outlier_detection.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
#
1313
# License: BSD 3 clause
1414

15+
import warnings
1516
import numpy as np
1617
import scipy as sp
1718
from . import MinCovDet
1819
from ..base import ClassifierMixin
20+
from ..utils.validation import check_is_fitted
1921

2022

2123
class OutlierDetectionMixin(object):
@@ -36,7 +38,6 @@ class OutlierDetectionMixin(object):
3638
"""
3739
def __init__(self, contamination=0.1):
3840
self.contamination = contamination
39-
self.threshold = None
4041

4142
def decision_function(self, X, raw_values=False):
4243
"""Compute the decision function of the given observations.
@@ -62,14 +63,14 @@ def decision_function(self, X, raw_values=False):
6263
such as the One-Class SVM.
6364
6465
"""
66+
check_is_fitted(self, 'threshold_')
6567
mahal_dist = self.mahalanobis(X)
6668
if raw_values:
6769
decision = mahal_dist
6870
else:
69-
if self.threshold is None:
70-
raise Exception("Please fit data before predicting")
71+
check_is_fitted(self, 'threshold_')
7172
transformed_mahal_dist = mahal_dist ** 0.33
72-
decision = self.threshold ** 0.33 - transformed_mahal_dist
73+
decision = self.threshold_ ** 0.33 - transformed_mahal_dist
7374

7475
return decision
7576

@@ -90,17 +91,23 @@ def predict(self, X):
9091
The values of the less outlying point's decision function.
9192
9293
"""
93-
if self.threshold is None:
94-
raise Exception("Please fit data before predicting")
94+
check_is_fitted(self, 'threshold_')
9595
is_inlier = -np.ones(X.shape[0], dtype=int)
9696
if self.contamination is not None:
9797
values = self.decision_function(X, raw_values=True)
98-
is_inlier[values <= self.threshold] = 1
98+
is_inlier[values <= self.threshold_] = 1
9999
else:
100100
raise NotImplementedError("You must provide a contamination rate.")
101101

102102
return is_inlier
103103

104+
@property
105+
def threshold(self):
106+
warnings.warn(("The threshold attribute is renamed to threshold_ from "
107+
"0.16 onwards and will be removed in 0.18"),
108+
DeprecationWarning, stacklevel=1)
109+
return getattr(self, 'threshold_', None)
110+
104111

105112
class EllipticEnvelope(ClassifierMixin, OutlierDetectionMixin, MinCovDet):
106113
"""An object for detecting outliers in a Gaussian distributed dataset.
@@ -175,10 +182,7 @@ def __init__(self, store_precision=True, assume_centered=False,
175182
OutlierDetectionMixin.__init__(self, contamination=contamination)
176183

177184
def fit(self, X, y=None):
178-
"""
179-
"""
180185
MinCovDet.fit(self, X)
181-
self.threshold = sp.stats.scoreatpercentile(
186+
self.threshold_ = sp.stats.scoreatpercentile(
182187
self.dist_, 100. * (1. - self.contamination))
183-
184188
return self

sklearn/covariance/tests/test_robust_covariance.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from sklearn.utils.testing import assert_almost_equal
1010
from sklearn.utils.testing import assert_array_almost_equal
1111
from sklearn.utils.testing import assert_raises
12+
from sklearn.utils.validation import NotFittedError
1213

1314
from sklearn import datasets
1415
from sklearn.covariance import empirical_covariance, MinCovDet, \
@@ -82,9 +83,8 @@ def test_outlier_detection():
8283
rnd = np.random.RandomState(0)
8384
X = rnd.randn(100, 10)
8485
clf = EllipticEnvelope(contamination=0.1)
85-
print(clf.threshold)
86-
assert_raises(Exception, clf.predict, X)
87-
assert_raises(Exception, clf.decision_function, X)
86+
assert_raises(NotFittedError, clf.predict, X)
87+
assert_raises(NotFittedError, clf.decision_function, X)
8888
clf.fit(X)
8989
y_pred = clf.predict(X)
9090
decision = clf.decision_function(X, raw_values=True)

0 commit comments

Comments
 (0)