scikit-learn adapter¶
probcal.sklearn (extra: pip install "probcal[sklearn]", scikit-learn ≥ 1.4)
provides two estimators. Neither is imported by import probcal — the core
stays numpy-only.
Ending a pipeline with a calibrated column¶
SklearnCalibrator is score-level: its X is the score itself, one column
((n,) or (n, 1); more columns raise). Use it wherever sklearn expects an
estimator, or let transform end a Pipeline:
from probcal import BetaCalibrator
from probcal.sklearn import SklearnCalibrator
est = SklearnCalibrator(BetaCalibrator()).fit(scores, y)
est.predict_proba(scores_new) # (n, 2)
est.transform(scores_new) # (n, 1) calibrated column
est.calibrator_.interpret() # the full probcal audit surface
est.calibrator_.interval_inverse(0.0, 0.02, space="logit")
est.calibrator_.to_json("calibrator.json")
Score columns on the margin scale are declared, not guessed:
SklearnCalibrator(input="logit") maps them through expit exactly first.
Cross-validated calibration of a classifier¶
CalibratedClassifier is the drop-in for
sklearn.calibration.CalibratedClassifierCV(ensemble=False):
from sklearn.ensemble import HistGradientBoostingClassifier
from probcal.sklearn import CalibratedClassifier
clf = CalibratedClassifier(
HistGradientBoostingClassifier(), cv=5, random_state=0
).fit(X_train, y_train)
clf.predict_proba(X_new)
# probcal calibrator protocol, delegated — hand clf straight to treecf:
clf.interval_inverse(0.0, 0.02, space="logit")
clf.fingerprint()
cv="prefit" scores the calibration set with the already-fitted estimator;
method="decision_function" maps margins through expit before calibration
(the calibrator absorbs the monotone distortion this introduces).
Grid search over the calibration map¶
The probcal calibrator is a nested estimator, so its parameters are grid-searchable:
from sklearn.model_selection import GridSearchCV
gs = GridSearchCV(
CalibratedClassifier(model, calibrator=BetaCalibrator()),
{"calibrator__variant": ["a", "ab", "abm"]},
scoring="neg_log_loss",
cv=5,
).fit(X, y)
Against CalibratedClassifierCV¶
CalibratedClassifierCV(ensemble=False) |
probcal.sklearn.CalibratedClassifier |
|
|---|---|---|
| OOF protocol, one map, full refit | yes | yes (verified equivalent) |
| Calibration methods | sigmoid, isotonic | all 12 probcal calibrators + CalibratorSelector |
| Parameter interpretation | — | interpret() on the fitted map |
| Metric CIs | — | probcal.metrics.evaluate bootstrap |
| Exact inverse maps (policy → raw threshold) | — | interval_inverse / point_inverse, delegated |
| Serialization | pickle | versioned JSON + fingerprint() (and pickle) |
| Multiclass | yes | binary only, by design |
Estimator-check compliance¶
Both estimators run sklearn.utils.estimator_checks.parametrize_with_checks
in CI on the pinned minimum (1.4) and the latest release.
CalibratedClassifier passes the full corpus except the sample-weight ≡
duplication equivalence, which cannot hold through a CV split whose fold
assignment depends on n (sklearn's own CV wrappers share this; declared via
expected_failed_checks). SklearnCalibrator's one-column contract is
inapplicable to the generic multi-feature checks — those are declared
expected failures with the reason stated, the same domain-restriction sklearn
special-cases its own IsotonicRegression for; the remaining convention
checks run live.