Persisting calibrators¶
Data these snippets assume
Blocks on this page use a fixed set of names for held-out data instead of re-deriving it each time. To run them, define the names first:
# docs: no-run — the definitions the snippets on this page assume
import numpy as np
from probcal import BetaCalibrator, Masterscale, make_pd_portfolio
from probcal.monitor import CalibrationMonitor
cal_set, new_set = make_pd_portfolio(n=3000, random_state=0), make_pd_portfolio(n=1000, random_state=1)
s_cal, y_cal = cal_set.scores, cal_set.y # held-out calibration scores and outcomes
w_cal = np.ones_like(y_cal) # uniform sample weights
s_new = new_set.scores # scores of new obligors
ms = Masterscale.from_edges([0.01, 0.05], names=["G1", "G2", "G3"]) # the masterscale
p_cal = BetaCalibrator().fit(s_cal, y_cal).predict_proba(s_cal) # calibrated PDs
grades = ms.assign(p_cal) # rating labels
segments = np.array(["seg-a", "seg-b", "seg-c"])[np.arange(len(s_cal)) % 3] # segment labels
model = ... # any object with predict_proba(X); the docs use a stub that reads X[:, 0]
mon = CalibrationMonitor(alpha=0.05) # with a few batches of a calibrated forecast applied
Every block also names, in its first comment line, which of these it uses.
How-to; what is stored, why JSON and never pickle, and the compatibility promise live in the Serialization concepts chapter.
# s_cal, y_cal: held-out calibration scores and outcomes
import json
from probcal import BetaCalibrator
cal = BetaCalibrator().fit(s_cal, y_cal)
text = cal.to_json() # human-readable, versioned string
cal.to_json("calibrator.json") # or straight to a file
loaded = BetaCalibrator.from_json("calibrator.json")
# ...or without knowing the class:
from probcal import BaseCalibrator
loaded = BaseCalibrator.from_dict(json.loads(text)) # registry dispatch
cal.fingerprint() # sha-256 provenance id (identical fits match)
cal.fit_meta_["data_fingerprint"] # sha-256 of the sorted training triple
Objects with external parts keep them as references, never blobs:
CalibratedModel.from_dict(d, model=...) reattaches the base model;
CalibratedScorecard.from_dict(d, scorecard=...) verifies the scorecard
table's fingerprint before attaching. The monitor serializes its whole
past (CalibrationMonitor.from_json resumes bit-for-bit).
Every 0.x release reads schema 1, enforced by committed golden files in CI rather than promised on trust.