Skip to content

Commit 919ca41

Browse files
ENH - Rename MapieCalibrator to TopLabelCalibrator and remove unused method parameter (#687)
1 parent ec04387 commit 919ca41

File tree

6 files changed

+42
-84
lines changed

6 files changed

+42
-84
lines changed

doc/api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Calibration
4141
:toctree: generated/
4242
:template: class.rst
4343

44-
mapie.calibration.MapieCalibrator
44+
mapie.calibration.TopLabelCalibrator
4545

4646
Calibration Metrics
4747
======================================

doc/theoretical_description_binary_classification.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Definition 3 (Approximate calibration) [1].
8282
.. math::
8383
|\mathbb{E}[Y|\hat{\mu}(X)] - \hat{\mu}(X)| \leq \epsilon
8484
85-
See :class:`~sklearn.calibration.CalibratedClassifierCV` or :class:`~mapie.calibration.MapieCalibrator`
85+
See :class:`~sklearn.calibration.CalibratedClassifierCV` or :class:`~mapie.calibration.TopLabelCalibrator`
8686
to use a calibrator.
8787

8888
In the CP framework, it is worth noting that Venn predictors produce probability-type predictions

examples/classification/4-tutorials/plot_main-tutorial-binary-classification.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
Instead, we recommend the use of calibration (see more details in the
2323
Calibration section of the documentation or by using the
2424
:class:`~sklearn.calibration.CalibratedClassifierCV` proposed by sklearn
25-
or :class:`~mapie.calibration.MapieCalibrator` proposed in MAPIE).
25+
or :class:`~mapie.calibration.TopLabelCalibrator` proposed in MAPIE).
2626
"""
2727

2828
from typing import List

mapie/calibration.py

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,11 @@
1818
_check_null_weight, _fit_estimator, _get_calib_set)
1919

2020

21-
class MapieCalibrator(BaseEstimator, ClassifierMixin):
21+
class TopLabelCalibrator(BaseEstimator, ClassifierMixin):
2222
"""
23-
Calibration for multi-class problems.
24-
25-
This class performs calibration for various methods, currently only
26-
top-label calibration [1].
23+
Top-label calibration for multi-class problems.
24+
Performs a calibration on the class with the highest score
25+
given both score and class, see section 2 of [1].
2726
2827
Parameters
2928
----------
@@ -33,13 +32,6 @@ class MapieCalibrator(BaseEstimator, ClassifierMixin):
3332
``None``.
3433
If ``None``, estimator defaults to a ``LogisticRegression`` instance.
3534
36-
method: Optional[str]
37-
The only valid method is "top_label".
38-
Performs a calibration on the class with highest score
39-
given both score and class, see section 2 of [1].
40-
41-
By default "top_label".
42-
4335
calibrator : Optional[Union[str, RegressorMixin]]
4436
Any calibrator with scikit-learn API
4537
(i.e. with fit, predict, and predict_proba methods), by default
@@ -62,9 +54,6 @@ class MapieCalibrator(BaseEstimator, ClassifierMixin):
6254
6355
Attributes
6456
----------
65-
valid_methods: List[str]
66-
List of all valid methods.
67-
6857
classes_: NDArray
6958
Array with the name of each class.
7059
@@ -90,10 +79,10 @@ class MapieCalibrator(BaseEstimator, ClassifierMixin):
9079
Examples
9180
--------
9281
>>> import numpy as np
93-
>>> from mapie.calibration import MapieCalibrator
82+
>>> from mapie.calibration import TopLabelCalibrator
9483
>>> X_toy = np.arange(9).reshape(-1, 1)
9584
>>> y_toy = np.stack([0, 0, 1, 0, 1, 2, 1, 2, 2])
96-
>>> mapie = MapieCalibrator().fit(X_toy, y_toy, random_state=20)
85+
>>> mapie = TopLabelCalibrator().fit(X_toy, y_toy, random_state=20)
9786
>>> y_calib = mapie.predict_proba(X_toy)
9887
>>> print(y_calib)
9988
[[0.84...... nan nan]
@@ -117,21 +106,17 @@ class MapieCalibrator(BaseEstimator, ClassifierMixin):
117106
"isotonic": IsotonicRegression(out_of_bounds="clip")
118107
}
119108

120-
valid_methods = ["top_label"]
121-
122109
valid_cv = ["prefit", "split"]
123110

124111
valid_inputs = ["multiclass", "binary"]
125112

126113
def __init__(
127114
self,
128115
estimator: Optional[ClassifierMixin] = None,
129-
method: str = "top_label",
130116
calibrator: Optional[Union[str, RegressorMixin]] = None,
131117
cv: Optional[str] = "split",
132118
) -> None:
133119
self.estimator = estimator
134-
self.method = method
135120
self.calibrator = calibrator
136121
self.cv = cv
137122

@@ -238,21 +223,6 @@ def _get_labels(
238223
y_pred = self.classes_[np.argmax(pred, axis=1)]
239224
return max_class_prob, y_pred
240225

241-
def _check_method(self) -> None:
242-
"""
243-
Check that the method is valid.
244-
245-
Raises
246-
------
247-
ValueError
248-
If the method does not belong to the valid methods.
249-
"""
250-
if self.method not in self.valid_methods:
251-
raise ValueError(
252-
"Invalid method, allowed method are: "
253-
+ (", ").join(self.valid_methods) + "."
254-
)
255-
256226
def _check_type_of_target(self, y: ArrayLike):
257227
"""
258228
Check type of target for calibration class.
@@ -431,7 +401,7 @@ def fit(
431401
shuffle: Optional[bool] = True,
432402
stratify: Optional[ArrayLike] = None,
433403
**fit_params,
434-
) -> MapieCalibrator:
404+
) -> TopLabelCalibrator:
435405
"""
436406
Calibrate the estimator on given datasets, according to the chosen
437407
method.
@@ -471,10 +441,9 @@ def fit(
471441
472442
Returns
473443
-------
474-
MapieCalibrator
444+
TopLabelCalibrator
475445
The model itself.
476446
"""
477-
self._check_method()
478447
cv = self._check_cv(self.cv)
479448
X, y = indexable(X, y)
480449
y = _check_y(y)

mapie/tests/test_calibration.py

Lines changed: 28 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from sklearn.pipeline import Pipeline, make_pipeline
1616
from sklearn.preprocessing import OneHotEncoder
1717

18-
from mapie.calibration import MapieCalibrator
18+
from mapie.calibration import TopLabelCalibrator
1919
from mapie.metrics.calibration import top_label_ece
2020
from mapie.metrics.calibration import expected_calibration_error
2121

@@ -110,20 +110,19 @@
110110

111111
def test_initialized() -> None:
112112
"""Test that initialization does not crash."""
113-
MapieCalibrator()
113+
TopLabelCalibrator()
114114

115115

116116
def test_default_parameters() -> None:
117117
"""Test default values of input parameters."""
118-
mapie_cal = MapieCalibrator()
119-
assert mapie_cal.method == "top_label"
118+
mapie_cal = TopLabelCalibrator()
120119
assert mapie_cal.calibrator is None
121120
assert mapie_cal.cv == "split"
122121

123122

124123
def test_default_fit_params() -> None:
125124
"""Test default sample weights and other parameters."""
126-
mapie_cal = MapieCalibrator()
125+
mapie_cal = TopLabelCalibrator()
127126
assert (
128127
signature(mapie_cal.fit).parameters["sample_weight"].default
129128
is None
@@ -152,15 +151,15 @@ def test_false_str_estimator() -> None:
152151
ValueError,
153152
match=r".*Please provide a string in*",
154153
):
155-
mapie_cal = MapieCalibrator(
154+
mapie_cal = TopLabelCalibrator(
156155
calibrator="not_estimator"
157156
)
158157
mapie_cal.fit(X, y)
159158

160159

161160
def test_estimator_none() -> None:
162161
"""Test that no input for calibrator will return a sigmoid"""
163-
mapie_cal = MapieCalibrator()
162+
mapie_cal = TopLabelCalibrator()
164163
mapie_cal.fit(X, y)
165164
assert isinstance(
166165
mapie_cal.calibrators[list(mapie_cal.calibrators.keys())[0]],
@@ -172,34 +171,24 @@ def test_check_type_of_target() -> None:
172171
"""Test the type of target."""
173172
X = [0.5, 0.2, 0.4, 0.8, 3.8]
174173
y = [0.4, 0.2, 3.6, 3, 0.2]
175-
mapie_cal = MapieCalibrator()
174+
mapie_cal = TopLabelCalibrator()
176175
with pytest.raises(
177176
ValueError,
178177
match=r".*Make sure to have one of the allowed targets:*"
179178
):
180179
mapie_cal.fit(X, y)
181180

182181

183-
def test_other_methods() -> None:
184-
"""Test that invalid string for method returns error"""
185-
with pytest.raises(
186-
ValueError,
187-
match=r".*Invalid method, allowed method are*",
188-
):
189-
mapie_cal = MapieCalibrator(method="no_method")
190-
mapie_cal.fit(X, y)
191-
192-
193182
def test_prefit_cv_argument() -> None:
194183
"""Test that prefit method works"""
195184
est = RandomForestClassifier().fit(X, y)
196-
mapie_cal = MapieCalibrator(estimator=est, cv="prefit")
185+
mapie_cal = TopLabelCalibrator(estimator=est, cv="prefit")
197186
mapie_cal.fit(X, y)
198187

199188

200189
def test_split_cv_argument() -> None:
201190
"""Test that split method works"""
202-
mapie_cal = MapieCalibrator(cv="split")
191+
mapie_cal = TopLabelCalibrator(cv="split")
203192
mapie_cal.fit(X, y)
204193

205194

@@ -210,7 +199,7 @@ def test_invalid_cv_argument(cv: str) -> None:
210199
ValueError,
211200
match=r".*Invalid cv argument*",
212201
):
213-
mapie_cal = MapieCalibrator(cv=cv)
202+
mapie_cal = TopLabelCalibrator(cv=cv)
214203
mapie_cal.fit(X, y)
215204

216205

@@ -219,10 +208,10 @@ def test_prefit_split_same_results() -> None:
219208
est = RandomForestClassifier(
220209
random_state=random_state
221210
).fit(X_train, y_train)
222-
mapie_cal_prefit = MapieCalibrator(estimator=est, cv="prefit")
211+
mapie_cal_prefit = TopLabelCalibrator(estimator=est, cv="prefit")
223212
mapie_cal_prefit.fit(X_calib, y_calib)
224213

225-
mapie_cal_split = MapieCalibrator(
214+
mapie_cal_split = TopLabelCalibrator(
226215
estimator=RandomForestClassifier(random_state=random_state)
227216
)
228217
mapie_cal_split.fit(
@@ -242,7 +231,7 @@ def test_not_seen_calibrator() -> None:
242231
UserWarning,
243232
match=r".*WARNING: This predicted label*"
244233
):
245-
mapie_cal = MapieCalibrator()
234+
mapie_cal = TopLabelCalibrator()
246235
mapie_cal.fit(X, y)
247236
mapie_cal.calibrators.clear()
248237
mapie_cal.predict_proba(X)
@@ -255,7 +244,7 @@ def test_shape_of_output(
255244
estimator: ClassifierMixin
256245
) -> None:
257246
"""Test that the size of the outputs are coherent."""
258-
mapie_cal = MapieCalibrator(
247+
mapie_cal = TopLabelCalibrator(
259248
estimator=estimator,
260249
calibrator=calibrator,
261250
)
@@ -269,7 +258,7 @@ def test_number_of_classes_equal_calibrators() -> None:
269258
Test that the number of calibrators is the same as the number
270259
of classes in the calibration step.
271260
"""
272-
mapie_cal = MapieCalibrator()
261+
mapie_cal = TopLabelCalibrator()
273262
mapie_cal.fit(
274263
X=X_,
275264
y=y_,
@@ -281,7 +270,7 @@ def test_number_of_classes_equal_calibrators() -> None:
281270

282271
def test_same_predict() -> None:
283272
"""Test that the same prediction is made regardless of the calibration."""
284-
mapie_cal = MapieCalibrator(method="top_label")
273+
mapie_cal = TopLabelCalibrator()
285274
mapie_cal.fit(
286275
X=X_,
287276
y=y_,
@@ -300,13 +289,13 @@ def test_same_predict() -> None:
300289
)
301290

302291

303-
@pytest.mark.parametrize("cv", MapieCalibrator.valid_cv)
292+
@pytest.mark.parametrize("cv", TopLabelCalibrator.valid_cv)
304293
def test_correct_results(cv: str) -> None:
305294
"""
306295
Test that the y_score and top label score from the test dataset result
307296
in the correct scores (in a multi-class setting).
308297
"""
309-
mapie_cal = MapieCalibrator(cv=cv)
298+
mapie_cal = TopLabelCalibrator(cv=cv)
310299
mapie_cal.fit(
311300
X=X_,
312301
y=y_,
@@ -326,7 +315,7 @@ def test_correct_results(cv: str) -> None:
326315
)
327316

328317

329-
@pytest.mark.parametrize("cv", MapieCalibrator.valid_cv)
318+
@pytest.mark.parametrize("cv", TopLabelCalibrator.valid_cv)
330319
def test_correct_results_binary(cv: str) -> None:
331320
"""
332321
Test that the y_score and top label score from the test dataset result
@@ -338,7 +327,7 @@ def test_correct_results_binary(cv: str) -> None:
338327
n_informative=4,
339328
random_state=random_state
340329
)
341-
mapie_cal = MapieCalibrator(cv=cv)
330+
mapie_cal = TopLabelCalibrator(cv=cv)
342331
mapie_cal.fit(
343332
X=X_binary,
344333
y=y_binary,
@@ -375,17 +364,17 @@ def test_different_binary_y_combinations() -> None:
375364
n_informative=4,
376365
random_state=random_state
377366
)
378-
mapie_cal = MapieCalibrator()
367+
mapie_cal = TopLabelCalibrator()
379368
mapie_cal.fit(X_comb, y_comb, random_state=random_state)
380369
y_score = mapie_cal.predict_proba(X_comb)
381370

382371
y_comb1 = np.where(y_comb == 2, 3, y_comb)
383-
mapie_cal1 = MapieCalibrator()
372+
mapie_cal1 = TopLabelCalibrator()
384373
mapie_cal1.fit(X_comb, y_comb1, random_state=random_state)
385374
y_score1 = mapie_cal1.predict_proba(X_comb)
386375

387376
y_comb2 = np.where(y_comb == 2, 40, y_comb)
388-
mapie_cal2 = MapieCalibrator()
377+
mapie_cal2 = TopLabelCalibrator()
389378
mapie_cal2.fit(X_comb, y_comb2, random_state=random_state)
390379
y_score2 = mapie_cal2.predict_proba(X_comb)
391380
np.testing.assert_array_almost_equal(y_score, y_score1)
@@ -417,9 +406,9 @@ def test_results_with_constant_sample_weights(
417406
"""
418407
n_samples = len(X)
419408
estimator = RandomForestClassifier(random_state=random_state)
420-
mapie_clf0 = MapieCalibrator(estimator=estimator, calibrator=calibrator)
421-
mapie_clf1 = MapieCalibrator(estimator=estimator, calibrator=calibrator)
422-
mapie_clf2 = MapieCalibrator(estimator=estimator, calibrator=calibrator)
409+
mapie_clf0 = TopLabelCalibrator(estimator=estimator, calibrator=calibrator)
410+
mapie_clf1 = TopLabelCalibrator(estimator=estimator, calibrator=calibrator)
411+
mapie_clf2 = TopLabelCalibrator(estimator=estimator, calibrator=calibrator)
423412
mapie_clf0.fit(X, y, sample_weight=None, random_state=random_state)
424413
mapie_clf1.fit(
425414
X, y, sample_weight=np.ones(shape=n_samples),
@@ -463,7 +452,7 @@ def test_pipeline_compatibility() -> None:
463452
)
464453
pipe = make_pipeline(preprocessor, LogisticRegression())
465454
pipe.fit(X, y)
466-
mapie = MapieCalibrator(estimator=pipe)
455+
mapie = TopLabelCalibrator(estimator=pipe)
467456
mapie.fit(X, y)
468457
mapie.predict(X)
469458

@@ -476,7 +465,7 @@ def test_fit_parameters_passing() -> None:
476465
"""
477466
gb = GradientBoostingClassifier(random_state=random_state)
478467

479-
mapie = MapieCalibrator(estimator=gb)
468+
mapie = TopLabelCalibrator(estimator=gb)
480469

481470
def early_stopping_monitor(i, est, locals):
482471
"""Returns True on the 3rd iteration."""

0 commit comments

Comments
 (0)