Out-of-Sample Assessment¶
Does a candidate predictor of model bias still work where you did not measure?
That is a different question from "does it fit?", and it is the only one that matters when the point of a bias correction is to reach the ungauged terrain between the gauges. A predictor fitted and scored on the same points will nearly always look useful.
Predicting a point from a group that contains it is not out-of-sample
loo_cluster_pred recomputes each group's mean without
the point being predicted. Including it is the standard way to make a regionalisation look
skilful when it is merely descriptive — the point is partly predicting itself, and the effect is
largest for exactly the small groups a clustering tends to produce.
A singleton group falls back to the leave-one-out global mean, because a group of one carries no information about itself.
The baseline matters as much as the method¶
loo_global_mean is the aspatial baseline — "correct
everything by the same amount". Any regionalisation, covariate or clustering has to beat this to
have earned its complexity, and a surprising amount of apparent skill disappears when it is measured
against a leave-one-out global mean rather than against no correction at all.
Turn two sets of residuals into one number with
compute_residual_skill_score — positive means the method beat the baseline, negative
means the baseline won, which is the outcome worth reporting rather than hiding.
Nothing here is spatial¶
loo_cluster_pred takes values and labels. The labels may come from a spatial clustering
(modverif.spatial.best_kmeans) or from anything else — land-use class, elevation
band, forecast regime. That is why these live apart from the structure diagnostics.
API¶
Out-of-sample assessment of candidate predictors for a scattered error field.
The question here is not "does this predictor fit?" but "does it still work where you did not measure?" -- which is the only version that matters when the point of a bias correction is to reach the ungauged terrain between the gauges.
Nothing in this module is spatial. loo_cluster_pred takes values and labels; the labels may come
from a spatial clustering (modverif.spatial.best_kmeans) or from anything else. Keeping these
apart from the structure diagnostics is what makes them findable by the next consumer, who may have
no variogram in sight.
Pair the residuals these produce with modverif.metrics.compute_residual_skill_score, which is the
common way to turn two sets of residuals into a single "did it beat the baseline?" number.
cluster_holdout(pred_fn, values, labels)
¶
Leave-one-group-out: predict each held-out group from all the others.
Much harsher than leave-one-out, and much closer to the real question. Leave-one-out leaves a point surrounded by its own neighbours; leaving out a whole region asks whether the relationship transfers to somewhere it was never fitted. A regionalisation that scores well under leave-one-out and badly here is describing the gauges, not the field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pred_fn
|
callable
|
|
required |
values
|
ndarray
|
Field being predicted. |
required |
labels
|
ndarray
|
Group label per point. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Skill against the training-set mean of each fold. |
holdout_high(covariate, values, q)
¶
Train on the low end of a covariate and predict the high end -- an extrapolation test.
This is the decisive check when the operational claim is "correct the bias where we have no measurements", and the ungauged places sit at the extreme of the covariate. Rain gauges cluster in valleys, so a correction applied to ridges extrapolates the elevation slope beyond any support in the data. Leave-one-out cannot detect that; withholding the top of the range can.
A negative skill here is the informative result: it says the relationship, however significant in-sample, does not reach the places the correction was wanted for.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
covariate
|
ndarray
|
Predictor per point. The highest |
required |
values
|
ndarray
|
Field being predicted. |
required |
q
|
float
|
Fraction to withhold; at least 2 points are always held out. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
skill |
float
|
|
diagnostics |
tuple
|
|
loo_cluster_pred(z, labels)
¶
Leave-one-out prediction from cluster means.
Each point is predicted from its own cluster's mean computed without it. Including the point in its own predictor is the standard way to make a regionalisation look skilful when it is merely descriptive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
ndarray
|
Field values. |
required |
labels
|
ndarray
|
Cluster label per point. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Prediction per point. A singleton cluster falls back to the leave-one-out global mean, since a cluster of one carries no information about itself. |
loo_global_mean(z)
¶
Leave-one-out global mean -- the aspatial baseline any regionalisation must beat.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
ndarray
|
Field values. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Mean of all other points, per point. |
loo_theilsen(covariate, values)
¶
Leave-one-out Theil--Sen prediction of values from a scalar covariate.
Refits the regression n times, each time omitting the point being predicted. Theil--Sen rather than least squares because a bias field's relationship to a covariate is usually driven by the bulk of the points, and a handful of extreme stations should not set the slope.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
covariate
|
ndarray
|
Predictor per point -- elevation, distance to coast, whatever is being assessed. |
required |
values
|
ndarray
|
Field being predicted, typically |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Out-of-sample prediction per point. |
Notes
Leave-one-out still shares most of the training set between folds, so it is the mildest
honest test available. It says nothing about whether the relationship extrapolates beyond
the range the points cover -- for that, use holdout_high.