Roadmap: ensemble-statistics and same-run NWP interpolation experiments - #495
Merged
Conversation
JackKelly
force-pushed
the
claude/nwp-ensemble-roadmap
branch
4 times, most recently
from
August 10, 2026 11:38
daa1f8f to
e11f197
Compare
Two new experiments on the XGBoost improvements page, both arising from the 2026-08-09 ECMWF ingest failure. Tier 3 — make the existing NWP null-filling deliberate, bounded and visible. The page previously said the chronic de-accumulated nulls "should be left un-imputed", but `_upsample_nwp_to_half_hourly` resamples to the half-hourly grid with `interpolate()`, which fills *interior* nulls as a side effect. So interior nulls are already imputed today, silently and unflagged; only leading nulls survive to the model. The experiment is therefore not "should we start interpolating" but "the interpolation already happening should be bounded, flagged and measured". Also records why filling within a run is the only fill worth having: ECMWF regenerates its perturbations every cycle, so member 34 of today's run is not member 34 of yesterday's. Tier 4 — ensemble statistics (quantiles) as features instead of member-by-member rows. Records the advantages (resilience to a missing member or variable, up to 51x fewer rows, spread as an explicit input, no member-identity problem) against the disadvantages (loses the weather-versus-model uncertainty decomposition and the source for delivery Representation 3, aggregates in weather space rather than power space, per-variable quantiles break cross-variable coherence, 51x less training data, moves the AllFeatures primary key). Separates representative-member subsampling as the smaller, coherence-preserving bet, and notes the item is an alternative to #148 at the same fork. Co-Authored-By: Claude <noreply@anthropic.com>
JackKelly
force-pushed
the
claude/nwp-ensemble-roadmap
branch
from
August 10, 2026 11:46
e11f197 to
6fe244d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Written by Claude Code, at Jack's direction, following the investigation of the failed
2026-08-09
ecmwf_enspartition.Stacked on #493 — it
branches from that PR and links to two anchors the rewritten known-issues page introduces, so
merge #493 first. The diff shown here is docs-only once #493 lands.
Two new experiments on XGBoost improvements,
both prompted by the 2026-08-09 ingest failure and the discussion it started about how the
pipeline should treat missing NWP.
Tier 2 — fill occasional NWP nulls by interpolating within the same run
Framed as the experiment that tests the page's standing "leave the chronic de-accumulated nulls
un-imputed" position rather than assuming it either way.
The substantive content is why same-run interpolation is the only fill worth trying. Filling
from the previous run is the obvious idea and it is the wrong one: ECMWF regenerates its
perturbations every cycle, so ensemble member 34 of today's 00Z run and member 34 of yesterday's
are not the same trajectory continued — they are two unrelated draws sharing a label, and only
member 0 (the unperturbed control) is comparable across runs. A cross-run fill would graft one
weather scenario's irradiance into another scenario's row, which for solar breaks coherence
between exactly the pair of variables that must agree. Neighbouring steps within a run are the
same trajectory, so that problem disappears — and no row ends up mixing NWP lead times either.
Also records where the fill belongs (the feature engineer, never the ingest, on provenance
grounds), the
is_imputedflag that makes a win interpretable, and two caveats: these are ratesover the preceding step, so interpolating across a 6-hourly gap is coarse exactly in the 3–10 day
band users act on; and training on filled inputs reintroduces train/serve skew.
Tier 4 — ensemble statistics (quantiles) instead of member-by-member rows
Placed next to "Train on more ensemble members" (#148),
because the two are alternatives at the same fork rather than sequential steps — worth deciding
together.
Argues for quantiles (p10/p25/p50/p75/p90) rather than mean and spread: mean-and-spread assumes
a near-Gaussian member distribution, which cloud cover badly violates ("half the members overcast,
half clear" is common, consequential, and its mean describes no member at all). Quantiles keep the
marginal shape at a ~5–10× row reduction rather than 51×, which makes it a much smaller bet while
testing the same idea.
Advantages recorded: resilience by construction (a missing member shifts a quantile instead of
removing rows — the 2026-08-09 incident would not have been an event); up to 51× fewer rows, which
eases the memory ceiling, the 32-bit row-index ceiling and the one-laptop principle at V2 scale;
spread as an explicit input, the natural feed for band-widening; and no member-identity problem.
Disadvantages recorded: it gives up the weather-versus-model uncertainty decomposition — with
no per-member conditional distribution there is no linear pool and no source for delivery
Representation 3, so the model cannot answer "is this uncertain because the weather is uncertain,
or because the model is?"; it aggregates in weather space rather than power space, which is the
wrong order of operations for a non-linear response; per-variable quantiles break cross-variable
coherence (a p90 irradiance and p90 temperature need not co-occur in any member); 51× less
training data, in direct tension with #148; and it moves the
AllFeaturesprimary key, soprinciple 8 requires a controlled comparison.
One honest counterweight is noted rather than buried: conflating the two uncertainty terms removes
the double-counting risk by construction, so the collapsed model might be better calibrated while
being less informative. Calibration and attribution are different goods.
Evaluation notes that this item specifically needs the probabilistic metrics, not just NMAE —
"matches on NMAE, loses on spread-skill" is the result that would tell you the decomposition was
doing real work.
Verification
pymarkdown scanandmkdocs build --strictpass, and the rendered HTML for the new sections wasread (10 list items, 3 nested lists, all labels intact) — Python-Markdown's list handling is
stricter than the linters catch.
Not included
No GitHub issues created for either experiment yet — say the word and I'll open them against the
right epic with the usual labels/Type/project fields.
🤖 Generated with Claude Code