7
7
from scipy import sparse
8
8
9
9
from sklearn .base import BaseEstimator
10
+ from sklearn .dummy import DummyClassifier
10
11
from sklearn .model_selection import LeaveOneOut , train_test_split
11
12
12
13
from sklearn .utils ._testing import (assert_array_almost_equal ,
26
27
from sklearn .pipeline import Pipeline
27
28
from sklearn .impute import SimpleImputer
28
29
from sklearn .metrics import brier_score_loss
29
- from sklearn .calibration import CalibratedClassifierCV
30
+ from sklearn .calibration import CalibratedClassifierCV , _CalibratedClassifier
30
31
from sklearn .calibration import _sigmoid_calibration , _SigmoidCalibration
31
32
from sklearn .calibration import calibration_curve
32
33
@@ -275,6 +276,29 @@ def multiclass_brier(y_true, proba_pred, n_classes):
275
276
assert calibrated_brier < 1.1 * uncalibrated_brier
276
277
277
278
279
+ def test_calibration_zero_probability ():
280
+ # Test an edge case where _CalibratedClassifier avoids numerical errors
281
+ # in the multiclass normalization step if all the calibrators output
282
+ # are zero all at once for a given sample and instead fallback to uniform
283
+ # probabilities.
284
+ class ZeroCalibrator ():
285
+ # This function is called from _CalibratedClassifier.predict_proba.
286
+ def predict (self , X ):
287
+ return np .zeros (X .shape [0 ])
288
+
289
+ X , y = make_blobs (n_samples = 50 , n_features = 10 , random_state = 7 ,
290
+ centers = 10 , cluster_std = 15.0 )
291
+ clf = DummyClassifier ().fit (X , y )
292
+ calibrator = ZeroCalibrator ()
293
+ cal_clf = _CalibratedClassifier (
294
+ base_estimator = clf , calibrators = [calibrator ], classes = clf .classes_ )
295
+
296
+ probas = cal_clf .predict_proba (X )
297
+
298
+ # Check that all probabilities are uniformly 1. / clf.n_classes_
299
+ assert_allclose (probas , 1. / clf .n_classes_ )
300
+
301
+
278
302
def test_calibration_prefit ():
279
303
"""Test calibration for prefitted classifiers"""
280
304
n_samples = 50
0 commit comments