Metrics¶
online_cp.metrics.Metric
¶
Base class for online evaluation metrics.
Subclasses must implement _score(self, y, Gamma, **kw) which
returns a single scalar for one observation.
Source code in src/online_cp/metrics.py
values: NDArray[np.floating[Any]]
property
¶
Per-step history as a numpy array.
update(y: Any = None, Gamma: Any = None, **kw: Any) -> float
¶
Record one observation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y
|
scalar
|
True label / response. |
None
|
Gamma
|
ConformalPredictionSet or ConformalPredictionInterval
|
Prediction output from a conformal predictor. |
None
|
**kw
|
dict
|
Additional keyword arguments (p_values, cpd, epsilon, etc.). Each metric picks what it needs. |
{}
|
Returns:
| Type | Description |
|---|---|
float
|
The metric value for this observation. |
Source code in src/online_cp/metrics.py
get() -> float
¶
cumulative_mean() -> NDArray[np.floating[Any]]
¶
online_cp.metrics.Metrics
¶
Composite of multiple metrics, created via the + operator.
Calling :meth:update forwards the observation to every contained metric,
and :meth:get returns a {name: running_mean} dictionary.
Example
metric = ErrorRate() + SetSize() metric.update(y=1, Gamma={1, 2}) metric.get() {'ErrorRate': 0.0, 'SetSize': 2.0}
Source code in src/online_cp/metrics.py
online_cp.metrics.ErrorRate
¶
Bases: Metric
Error rate: fraction of times the true label is excluded.
For a prediction set / interval \(\Gamma^\epsilon\) at significance level \(\epsilon\), the per-step score is the miss indicator
and get() returns the running error rate \(\mathrm{Err}_n^\epsilon / n\).
This is a measure of validity rather than efficiency: for an (exactly)
valid conformal predictor the errors at level \(\epsilon\) behave like
independent Bernoulli(\(\epsilon\)) trials, so
\(\mathrm{Err}_n^\epsilon / n \to \epsilon\) almost surely [ALRW2 §2.1, §3.1].
Works for both classifiers (prediction sets) and regressors (intervals).
Source code in src/online_cp/metrics.py
online_cp.metrics.ObservedExcess
¶
Bases: Metric
Observed excess (OE): number of false labels in the prediction set.
Per-step score at significance level \(\epsilon\),
i.e. \(|\Gamma| - 1\) when the true label is covered and \(|\Gamma|\) when it is
not. get() returns the average over the stream.
Criterion type. OE is an observed (it depends on the realised label
\(y\)) and \(\epsilon\)-dependent criterion of efficiency. By
[ALRW2 §3.1.5, Thm 3.1] it is one of the four criteria (S, N, OF, OE) that
are conditionally strongly proper: the conditional-probability idealised
conformity measure \(A(x, y) = Q(y \mid x)\), and every refinement of it, is
optimal for OE. Intuitively, a conditionally proper criterion rewards
conformity scores that rank labels by their true conditional probability, so
optimising OE does not pull the underlying scorer away from the
Bayes-optimal ordering. Contrast with the prior \(\epsilon\)-dependent
counterpart :class:SetSize (N) and the \(\epsilon\)-free observed
counterpart :class:ObservedFuzziness (OF).
Smaller is better.
Source code in src/online_cp/metrics.py
online_cp.metrics.ObservedFuzziness
¶
Bases: Metric
Observed fuzziness (OF): sum of p-values for the false labels.
Given the system of conformal p-values \((p^{y'} : y' \in \mathbf{Y})\) for the test object, the per-step score is
the sum of p-values over all labels other than the realised one. get()
returns the average over the stream.
Criterion type. OF is an observed and \(\epsilon\)-free criterion of
efficiency (it needs no significance level, only the p-values). By
[ALRW2 §3.1.5, Thm 3.1] it is conditionally strongly proper — it shares
the optimal idealised conformity measures of S, N and OE, namely all
refinements of the conditional-probability measure \(A(x, y) = Q(y \mid x)\).
Being \(\epsilon\)-free, it summarises efficiency across all significance
levels at once, and is the natural \(\epsilon\)-free analogue of
:class:ObservedExcess (OE).
Requires the p_values keyword argument (a dict mapping each label to
its conformal p-value). Smaller is better.
Source code in src/online_cp/metrics.py
online_cp.metrics.SetSize
¶
Bases: Metric
Set size (N): number of labels in the prediction set.
Per-step score \(|\Gamma^\epsilon|\) at significance level \(\epsilon\);
get() returns the average. Intended for classification; for regression
use :class:IntervalWidth as the analogous sharpness measure.
Criterion type. N is a prior criterion (it ignores the realised label
\(y\)) and is \(\epsilon\)-dependent. By [ALRW2 §3.1.5, Thm 3.1] it is
conditionally strongly proper, sharing the optimal idealised conformity
measures of S, OF and OE. It is the prior counterpart of the observed
criterion :class:ObservedExcess (OE): where OE counts only false labels, N
counts all labels — including the true one, which a valid predictor covers
with probability \(1 - \epsilon\).
Smaller is better.
Source code in src/online_cp/metrics.py
online_cp.metrics.IntervalWidth
¶
Bases: Metric
Interval width: sharpness measure for regression.
Per-step score is the length \(u - \ell\) of the prediction interval
\(\Gamma^\epsilon = [\ell, u]\) produced at significance level \(\epsilon\);
get() returns the average. This is the regression analogue of
:class:SetSize (N): given (approximately) valid coverage, narrower
intervals are more informative.
Width alone does not penalise miscoverage, so it should be read together with
:class:ErrorRate; see :class:WinklerScore for a single proper score that
combines width and coverage.
Source code in src/online_cp/metrics.py
online_cp.metrics.WinklerScore
¶
Bases: Metric
Winkler interval score — a proper scoring rule for interval forecasts.
For a central \((1 - \epsilon)\) prediction interval \([\ell, u]\) the per-step score is
i.e. the interval width plus a coverage penalty, scaled by \(2/\epsilon\), for
realisations falling outside the interval. Unlike the pure efficiency
criteria (:class:SetSize, :class:IntervalWidth) this is a proper
scoring rule: it is minimised in expectation by the true central
\((1-\epsilon)\) interval, so it rewards calibration and sharpness jointly
rather than width alone. Smaller is better; an infinite interval yields an
infinite score.
Notes
Requires the prediction interval to expose .lower and .upper.
The significance level used for the \(2/\epsilon\) tail penalty is resolved
per score: an explicit epsilon keyword takes precedence; otherwise the
interval's own Gamma.epsilon attribute is used; if neither is available
it falls back to 0.1. It must be positive.
Source code in src/online_cp/metrics.py
online_cp.metrics.CRPS
¶
Bases: Metric
Continuous Ranked Probability Score (CRPS) for conformal predictive systems.
The CRPS of a predictive CDF \(F\) against an outcome \(y\) is \(\int_{-\infty}^{\infty} (F(t) - \mathbf{1}\{y \leq t\})^2 \, dt\), a proper scoring rule for distributional forecasts. For a conformal predictive distribution the integral is taken against the (randomised) predictive CDF \(Q_\tau\).
Deprecated
This class is retained for backward compatibility and simply delegates
to :class:TruncatedCRPS. The raw CRPS integral diverges for a conformal
predictive distribution because its tails are mass-deficient (they do not
reach 0 and 1); prefer :class:TruncatedCRPS or :class:ConformalCRPS,
which keep the score finite by truncating the integral or replacing the
Heaviside indicator, respectively.
Requires the cpd keyword argument (a conformal predictive distribution).
Source code in src/online_cp/metrics.py
Venn Prediction Metrics¶
online_cp.metrics.BrierScore
¶
Bases: Metric
Brier score for Venn predictor outputs — a proper scoring rule.
Scores the aggregated point probability \(p_{\text{point}}\) of a
:class:~online_cp.venn.VennPrediction with the multiclass Brier score
the squared \(\ell_2\) distance between the probability vector and the one-hot
outcome. The Brier score is a proper scoring rule, so it is minimised in
expectation by the true conditional class probabilities and rewards both
calibration and sharpness. The Venn point probability is the multiprobability
average and requires no renormalisation. Smaller is better; compare with
:class:LogLoss.
Requires the venn keyword argument (a VennPrediction object).
Source code in src/online_cp/metrics.py
online_cp.metrics.LogLoss
¶
Bases: Metric
Log loss (negative log-likelihood) for Venn outputs — a proper scoring rule.
Scores the aggregated point probability \(p_{\text{point}}\) of a
:class:~online_cp.venn.VennPrediction by
the negative log-probability assigned to the realised label. Like the Brier
score it is a proper scoring rule, but it penalises confident mistakes
far more severely (unboundedly as \(p_{\text{point}}[y] \to 0\)). The
probability is clipped to \([10^{-15}, 1]\) before taking the logarithm to
avoid \(-\infty\). Smaller is better; compare with :class:BrierScore.
Requires the venn keyword argument (a VennPrediction object).
Source code in src/online_cp/metrics.py
online_cp.metrics.Width
¶
Bases: Metric
Width (sharpness) of a Venn multiprobability prediction.
A Venn predictor outputs, for each label, an interval of probabilities (one entry per hypothesised label). This metric reports the mean width of those intervals,
averaged over labels \(k\) and taken across hypotheses \(h\). For binary predictions this reduces to \(|p_1 - p_0|\). Smaller width means a tighter (more decisive) multiprobability prediction; it measures sharpness, not validity, and is the Venn analogue of interval width.
Requires the venn keyword argument (a VennPrediction object).
Source code in src/online_cp/metrics.py
online_cp.metrics.CalibrationError
¶
Bases: Metric
Expected Calibration Error (ECE) for Venn predictor outputs.
Accumulates (predicted probability, true indicator) pairs from a stream of
:class:~online_cp.venn.VennPrediction objects, enabling post-hoc ECE
computation by binning. With \(B\) bins, the binned ECE is
where \(n_b\) is the number of predictions in bin \(b\), \(\bar{p}_b\) their mean
predicted probability and \(\bar{y}_b\) the observed frequency of the target
class; see :meth:ece.
Two modes:
use_hypothesis=False(default): evaluates the point estimate fromvenn.point. This is the aggregated probability and is typically well-calibrated empirically.use_hypothesis=True: evaluates the correct-hypothesis probability \(P^y(y)\), which is theoretically calibrated by the Venn validity guarantee [ALRW2, Thm 6.4].
The per-step _score() returns \(|p - \mathbf{1}\{y = k\}|\) (the absolute
calibration gap), so metric.get() gives the running mean absolute error.
Use :meth:ece for the standard binned ECE.
For binary classification, the tracked class defaults to label_space[1]
(the "positive" class). For multiclass, specify target_class explicitly.
Requires venn keyword argument (a VennPrediction object).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
use_hypothesis
|
bool
|
If True, use the correct-hypothesis probability :math: |
False
|
target_class
|
int or None
|
Which class to track calibration for. If None, defaults to
|
None
|
max_history
|
int or None
|
Maximum number of (predicted, observed) pairs to store. If None, stores all. When exceeded, oldest pairs are discarded. |
None
|
Source code in src/online_cp/metrics.py
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 | |
predicted: NDArray
property
¶
Array of stored predicted probabilities.
observed: NDArray
property
¶
Array of stored true indicators (always 1 for correct-class prob).
reset() -> None
¶
update(y: Any = None, Gamma: Any = None, **kw: Any) -> float
¶
Record one observation, respecting max_history for all state.
Source code in src/online_cp/metrics.py
ece(n_bins: int = 10, strategy: str = 'uniform') -> float
¶
Compute binned Expected Calibration Error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_bins
|
int
|
Number of bins. |
10
|
strategy
|
str
|
Binning strategy: |
"uniform"
|
Returns:
| Type | Description |
|---|---|
float
|
Weighted average of |mean_predicted - fraction_positive| across bins, weighted by bin count. |
Source code in src/online_cp/metrics.py
bin_data(n_bins: int = 10, strategy: str = 'uniform') -> tuple[NDArray, NDArray, NDArray]
¶
Return binned calibration data for plotting.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_bins
|
int
|
Number of bins. |
10
|
strategy
|
str
|
Binning strategy: |
"uniform"
|
Returns:
| Name | Type | Description |
|---|---|---|
mean_predicted |
ndarray
|
Mean predicted probability per bin. |
fraction_positive |
ndarray
|
Fraction of positive outcomes per bin. |
bin_counts |
ndarray
|
Number of samples per bin. |