IsotonicQuantileCalibrator#

class openstef_models.transforms.postprocessing.isotonic_quantile_calibrator.IsotonicQuantileCalibrator(**data: Any) None[source]

Bases: BaseModel, Transform[ForecastDataset, ForecastDataset]

Calibrate quantile predictions using isotonic regression.

The predicted quantiles do not always match the observed quantile levels. This transform learns a monotonic mapping from predicted quantile values to calibrated values, ensuring that predicted quantiles match observed empirical quantiles in the validation data.

How it works:

  1. Learning phase (fit()):

    For each quantile (e.g., P10, P50, P90):

    • Sorts predictions and actual values together

    • Optionally estimates local quantiles using adaptive windowing

    • Fits isotonic regression that maps predictions to actuals

    • Enforces monotonicity: higher predictions → higher calibrated values

  2. Prediction phase (transform()):

    • Applies learned isotonic mapping to each quantile

    • Out-of-bounds predictions are handled per configuration

    • Preserves monotonic ordering across quantiles

Parameters:
  • quantiles (list[Quantile] | None) – Quantiles to calibrate (e.g., [0.1, 0.5, 0.9]). If None, calibrates all quantiles found in the validation data.

  • y_min (float | None) – Minimum bound for calibrated predictions. If specified, all calibrated values will be at least y_min.

  • y_max (float | None) – Maximum bound for calibrated predictions. If specified, all calibrated values will be at most y_max.

  • out_of_bounds (Literal['nan', 'clip', 'raise']) – How to handle predictions outside training range: - ‘clip’ (default): Extend to closest training value - ‘nan’: Return NaN for out-of-bounds predictions - ‘raise’: Raise error for out-of-bounds predictions

  • use_local_quantile_estimation (bool) – Whether to estimate target quantiles from local neighborhoods before fitting isotonic regression. Useful when bias varies across prediction range.

  • window_size (int | None) – Window size for local quantile estimation. If None, uses adaptive sizing (max(_MIN_WINDOW_SIZE, n/10)). Only used when use_local_quantile_estimation=True.

Invariants

  • Validation data must contain both predictions and target values

  • Each quantile must have sufficient valid (non-NaN) data points

  • Calibrated quantiles maintain monotonic ordering if input quantiles do

Example

>>> from openstef_core.types import Quantile
>>> # Basic calibration
>>> calibrator = IsotonicQuantileCalibrator(
...     quantiles=[Quantile(0.1), Quantile(0.5), Quantile(0.9)]
... )
>>> calibrator.fit(validation_data)
>>> calibrated = calibrator.transform(new_predictions)
>>>
>>> # With local quantile estimation and bounds
>>> calibrator = IsotonicQuantileCalibrator(
...     quantiles=[Quantile(0.1), Quantile(0.5), Quantile(0.9)],
...     use_local_quantile_estimation=True,
...     y_min=0.0,  # Ensure non-negative predictions
...     out_of_bounds='clip'
... )
>>> calibrator.fit(validation_data)
>>> calibrated = calibrator.transform(new_predictions)
Parameters:

data (Any)

quantiles: list[Quantile] | None
y_min: float | None
y_max: float | None
out_of_bounds: Literal['nan', 'clip', 'raise']
use_local_quantile_estimation: bool
window_size: int | None
property is_fitted: bool

Check if the transform has been fitted.

fit(data: ForecastDataset) None[source]

Fit the transform to the input data.

This method should be called before applying the transform to the data. It allows the transform to learn any necessary parameters from the data.

Parameters:
Return type:

None

transform(data: ForecastDataset) ForecastDataset[source]

Transform the input data.

This method should apply a transformation to the input data and return a new instance.

Parameters:
Returns:

A new instance of the transformed data.

Raises:

NotFittedError – If the transform has not been fitted yet.

Return type:

ForecastDataset

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

  • self

  • context

Return type:

None