Skip to content

Commit c23039a

Browse files
Merge pull request #514 from scikit-learn-contrib/511-modulenotfounderror-no-module-named-mapieconformity_scoresresidual_conformity_scores
2 parents 9a0f359 + ae03b4f commit c23039a

File tree

5 files changed

+345
-1
lines changed

5 files changed

+345
-1
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
from abc import ABCMeta, abstractmethod
2+
3+
from sklearn.utils import deprecated
4+
5+
from mapie.conformity_scores.regression import BaseConformityScore
6+
from mapie._machine_precision import EPSILON
7+
from mapie._typing import NDArray
8+
9+
10+
@deprecated(
11+
"WARNING: Deprecated path to import ConformityScore. "
12+
"Please prefer the new path: "
13+
"[from mapie.conformity_scores import BaseRegressionScore]."
14+
)
15+
class ConformityScore(BaseConformityScore, metaclass=ABCMeta):
16+
"""
17+
Base conformity score class for regression task.
18+
19+
This class should not be used directly. Use derived classes instead.
20+
21+
Parameters
22+
----------
23+
sym: bool
24+
Whether to consider the conformity score as symmetrical or not.
25+
26+
consistency_check: bool, optional
27+
Whether to check the consistency between the methods
28+
``get_estimation_distribution`` and ``get_conformity_scores``.
29+
If ``True``, the following equality must be verified:
30+
``self.get_estimation_distribution(
31+
y_pred, self.get_conformity_scores(y, y_pred, **kwargs), **kwargs
32+
) == y``
33+
34+
By default ``True``.
35+
36+
eps: float, optional
37+
Threshold to consider when checking the consistency between
38+
``get_estimation_distribution`` and ``get_conformity_scores``.
39+
It should be specified if ``consistency_check==True``.
40+
41+
By default, it is defined by the default precision.
42+
"""
43+
44+
def __init__(
45+
self,
46+
sym: bool,
47+
consistency_check: bool = True,
48+
eps: float = float(EPSILON),
49+
):
50+
super().__init__()
51+
self.sym = sym
52+
self.consistency_check = consistency_check
53+
self.eps = eps
54+
55+
@abstractmethod
56+
def get_signed_conformity_scores(
57+
self,
58+
y: NDArray,
59+
y_pred: NDArray,
60+
**kwargs
61+
) -> NDArray:
62+
"""
63+
Placeholder for ``get_conformity_scores``.
64+
Subclasses should implement this method!
65+
66+
Compute the sample conformity scores given the predicted and
67+
observed targets.
68+
69+
Parameters
70+
----------
71+
y: NDArray of shape (n_samples,)
72+
Observed target values.
73+
74+
y_pred: NDArray of shape (n_samples,)
75+
Predicted target values.
76+
77+
Returns
78+
-------
79+
NDArray of shape (n_samples,)
80+
Signed conformity scores.
81+
"""
82+
83+
@abstractmethod
84+
def get_conformity_scores(
85+
self,
86+
y: NDArray,
87+
y_pred: NDArray,
88+
**kwargs
89+
) -> NDArray:
90+
"""
91+
Placeholder for ``get_conformity_scores``.
92+
Subclasses should implement this method!
93+
94+
Compute the sample conformity scores given the predicted and
95+
observed targets.
96+
97+
Parameters
98+
----------
99+
y: NDArray of shape (n_samples,)
100+
Observed target values.
101+
102+
y_pred: NDArray of shape (n_samples,)
103+
Predicted target values.
104+
105+
Returns
106+
-------
107+
NDArray of shape (n_samples,)
108+
Conformity scores.
109+
"""
110+
111+
@abstractmethod
112+
def get_estimation_distribution(
113+
self,
114+
y_pred: NDArray,
115+
conformity_scores: NDArray,
116+
**kwargs
117+
) -> NDArray:
118+
"""
119+
Placeholder for ``get_estimation_distribution``.
120+
Subclasses should implement this method!
121+
122+
Compute samples of the estimation distribution given the predicted
123+
targets and the conformity scores.
124+
125+
Parameters
126+
----------
127+
y_pred: NDArray of shape (n_samples,)
128+
Predicted target values.
129+
130+
conformity_scores: NDArray of shape (n_samples,)
131+
Conformity scores.
132+
133+
Returns
134+
-------
135+
NDArray of shape (n_samples,)
136+
Observed values.
137+
"""
138+
139+
@abstractmethod
140+
def predict_set(
141+
self,
142+
X: NDArray,
143+
alpha_np: NDArray,
144+
**kwargs
145+
):
146+
"""
147+
Compute the prediction sets on new samples based on the uncertainty of
148+
the target confidence set.
149+
150+
Parameters:
151+
-----------
152+
X: NDArray of shape (n_samples,)
153+
The input data or samples for prediction.
154+
155+
alpha_np: NDArray of shape (n_alpha, )
156+
Represents the uncertainty of the confidence set to produce.
157+
158+
**kwargs: dict
159+
Additional keyword arguments.
160+
161+
Returns:
162+
--------
163+
The output structure depend on the subclass.
164+
The prediction sets for each sample and each alpha level.
165+
"""
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
from sklearn.utils import deprecated
2+
3+
from .bounds import (
4+
AbsoluteConformityScore as NewAbsoluteConformityScore,
5+
GammaConformityScore as NewGammaConformityScore,
6+
ResidualNormalisedScore as NewResidualNormalisedScore
7+
)
8+
9+
10+
@deprecated(
11+
"WARNING: Deprecated path to import AbsoluteConformityScore. "
12+
"Please prefer the new path: "
13+
"[from mapie.conformity_scores.bounds import AbsoluteConformityScore]."
14+
)
15+
class AbsoluteConformityScore(NewAbsoluteConformityScore):
16+
pass
17+
18+
19+
@deprecated(
20+
"WARNING: Deprecated path to import GammaConformityScore. "
21+
"Please prefer the new path: "
22+
"[from mapie.conformity_scores.bounds import GammaConformityScore]."
23+
)
24+
class GammaConformityScore(NewGammaConformityScore):
25+
pass
26+
27+
28+
@deprecated(
29+
"WARNING: Deprecated path to import ResidualNormalisedScore. "
30+
"Please prefer the new path: "
31+
"[from mapie.conformity_scores.bounds import ResidualNormalisedScore]."
32+
)
33+
class ResidualNormalisedScore(NewResidualNormalisedScore):
34+
pass
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from sklearn.utils import deprecated
2+
3+
from mapie.conformity_scores.sets.utils import (
4+
get_true_label_position as get_true_label_position_new_path,
5+
)
6+
7+
8+
@deprecated(
9+
"WARNING: Deprecated path to import get_true_label_position. "
10+
"Please prefer the new path: "
11+
"[from mapie.conformity_scores.sets.utils import get_true_label_position]."
12+
)
13+
def get_true_label_position(*args, **kwargs):
14+
return get_true_label_position_new_path(*args, **kwargs)

mapie/estimator/estimator.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from sklearn.utils import deprecated
2+
3+
from mapie.estimator.regressor import EnsembleRegressor as NewEnsembleRegressor
4+
5+
6+
@deprecated(
7+
"WARNING: Deprecated path to import EnsembleRegressor. "
8+
"Please prefer the new path: "
9+
"[from mapie.estimator.regressor import EnsembleRegressor]."
10+
)
11+
class EnsembleRegressor(NewEnsembleRegressor):
12+
pass

mapie/tests/test_common.py

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
from sklearn.utils.estimator_checks import parametrize_with_checks
1212
from sklearn.utils.validation import check_is_fitted
1313

14+
from mapie._typing import ArrayLike, NDArray
1415
from mapie.classification import MapieClassifier
1516
from mapie.regression import MapieQuantileRegressor, MapieRegressor
1617

1718
X_toy = np.arange(18).reshape(-1, 1)
1819
y_toy = np.array(
1920
[0, 0, 1, 0, 1, 2, 1, 2, 2, 0, 0, 1, 0, 1, 2, 1, 2, 2]
20-
)
21+
)
2122

2223

2324
def MapieSimpleEstimators() -> List[BaseEstimator]:
@@ -195,3 +196,121 @@ def test_sklearn_compatible_estimator(
195196
) -> None:
196197
"""Check compatibility with sklearn, using sklearn estimator checks API."""
197198
check(estimator)
199+
200+
201+
def test_warning_when_import_from_gamma_conformity_score():
202+
"""Check that a DepreciationWarning is raised when importing from
203+
mapie.conformity_scores.residual_conformity_scores"""
204+
205+
with pytest.warns(
206+
FutureWarning, match=r".*WARNING: Deprecated path to import.*"
207+
):
208+
from mapie.conformity_scores.residual_conformity_scores import (
209+
GammaConformityScore
210+
)
211+
GammaConformityScore()
212+
213+
214+
def test_warning_when_import_from_absolute_conformity_score():
215+
"""Check that a DepreciationWarning is raised when importing from
216+
mapie.conformity_scores.residual_conformity_scores"""
217+
218+
with pytest.warns(
219+
FutureWarning, match=r".*WARNING: Deprecated path to import.*"
220+
):
221+
from mapie.conformity_scores.residual_conformity_scores import (
222+
AbsoluteConformityScore
223+
)
224+
AbsoluteConformityScore()
225+
226+
227+
def test_warning_when_import_from_residual_conformity_score():
228+
"""Check that a DepreciationWarning is raised when importing from
229+
mapie.conformity_scores.residual_conformity_scores"""
230+
231+
with pytest.warns(
232+
FutureWarning, match=r".*WARNING: Deprecated path to import.*"
233+
):
234+
from mapie.conformity_scores.residual_conformity_scores import (
235+
ResidualNormalisedScore
236+
)
237+
ResidualNormalisedScore()
238+
239+
240+
def test_warning_when_import_from_conformity_scores():
241+
"""Check that a DepreciationWarning is raised when importing from
242+
mapie.conformity_scores.conformity_score"""
243+
244+
with pytest.warns(
245+
FutureWarning, match=r".*WARNING: Deprecated path to import.*"
246+
):
247+
from mapie.conformity_scores.conformity_scores import (
248+
ConformityScore
249+
)
250+
251+
class DummyConformityScore(ConformityScore):
252+
def __init__(self) -> None:
253+
super().__init__(sym=True, consistency_check=True)
254+
255+
def get_signed_conformity_scores(
256+
self, y: ArrayLike, y_pred: ArrayLike, **kwargs
257+
) -> NDArray:
258+
return np.array([])
259+
260+
def get_estimation_distribution(
261+
self, y_pred: ArrayLike, conformity_scores: ArrayLike, **kwargs
262+
) -> NDArray:
263+
"""
264+
A positive constant is added to the sum between predictions and
265+
conformity scores to make the estimated distribution
266+
inconsistent with the conformity score.
267+
"""
268+
return np.array([])
269+
270+
def get_conformity_scores(
271+
self, y: ArrayLike, y_pred: ArrayLike, **kwargs
272+
) -> NDArray:
273+
return np.array([])
274+
275+
def predict_set(
276+
self, X: NDArray, alpha_np: NDArray, **kwargs
277+
) -> NDArray:
278+
return np.array([])
279+
280+
dcs = DummyConformityScore()
281+
dcs.get_signed_conformity_scores(y_toy, y_toy)
282+
dcs.get_estimation_distribution(y_toy, y_toy)
283+
dcs.get_conformity_scores(y_toy, y_toy)
284+
dcs.predict_set(y_toy, 0.5)
285+
286+
287+
def test_warning_when_import_from_old_get_true_label_position():
288+
"""Check that a DepreciationWarning is raised when importing from
289+
mapie.conformity_scores.residual_conformity_scores"""
290+
291+
with pytest.warns(
292+
FutureWarning, match=r".*WARNING: Deprecated path to import.*"
293+
):
294+
from mapie.conformity_scores.utils_classification_conformity_scores\
295+
import get_true_label_position
296+
get_true_label_position(np.array([[0.1, 0.2, 0.7]]), np.array([2]))
297+
298+
299+
def test_warning_when_import_from_estimator():
300+
"""Check that a DepreciationWarning is raised when importing from
301+
mapie.estimator.estimator"""
302+
303+
with pytest.warns(
304+
FutureWarning, match=r".*WARNING: Deprecated path to import.*"
305+
):
306+
from mapie.estimator.estimator import EnsembleRegressor
307+
EnsembleRegressor(
308+
estimator=LinearRegression(),
309+
method="naive",
310+
cv=3,
311+
agg_function="mean",
312+
n_jobs=1,
313+
random_state=0,
314+
test_size=0.2,
315+
verbose=0,
316+
)

0 commit comments

Comments
 (0)