Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

This chapter scores chapter 2’s test members with the register’s final incumbent, reads the score against no skill, and writes the justification, for a model-world result: a test on observed winters would have to come before any briefing line. It is not a blind test: during development (2026-10-20; the neural network also on 2026-10-29) these same 20 test members were scored with the Niño-sign rule, with logistic and boosting at the base-rate threshold, and, in the companion course, with a small neural network. Boosting at the base-rate threshold was registered as this cookbook’s final model on 2026-10-29, after those scores had been seen, so the test members took part in choosing the model. Read the edge below as provisional.

Overview

  1. Rebuild chapter 5’s register and take its final incumbent.

  2. Run the held-out test once.

  3. Read it against no skill and count false alarms against hits.

  4. Justify the decision and state the limits.

Shared code lives in lensml.py beside the chapters.

Prerequisites

ConceptsImportanceNotes
Chapter 5Helpfulthe register and its final incumbent
Chapter 4Helpfulprecision, recall and AP against the base rate
Bootstrap intervalsHelpfulresampling with replacement
  • Time to learn: about 15 minutes; rebuilding the register takes under a minute.

  • System requirements: the environment.yml at the repository root; no account, no local data beyond the committed cache.

Imports

cache header has no AUTUMN_MONTHS field (it predates the field): taken as AUTUMN_MONTHS=[9, 10, 11], the only autumn the derivation code had: the file's autumn is assumed, not read from the header. A rebuild records it.
train: 80 members / 9200 winters   test: 20 members / 2300 winters   N_FOLDS = 5

The final incumbent

The register is rebuilt exactly as chapter 5 left it (same trials, order and seeds); copy any YOUR_TRIALS you added there. Its incumbent was chosen after its validation score was seen, and these test members had already scored it (above).

first incumbent: nino-sign   fold draws per trial: 10 × 5 folds = 50 paired scores per metric
incumbent after 5 trials: boosting@base-rate
Bonferroni line after 5 tested row(s) = 10 looks: p < 0.0050   (at the cap of 6 rows: p < 0.0042). A row promoted on a p above this line is promoted under the uncorrected rule only.
Loading...

The test

The final model is fit once on all training members and scored on the test members. Change anything after reading the score and the test members become a validation set, to be reported as such; set FINAL = False while adding trials. The 95% intervals resample whole test members, so they cover only which members were drawn, not the choice of model or chapter 5’s selection.

test run #1
final model: boosting@base-rate   test members: 20   test winters: 2300   base rate: 0.335
precision (wet) = 0.353   recall (wet) = 0.662   wet-call share = 0.629   accuracy = 0.480   AP = 0.357
              precision    recall  f1-score   support

         dry       0.70      0.39      0.50      1530
         wet       0.35      0.66      0.46       770

    accuracy                           0.48      2300
   macro avg       0.52      0.53      0.48      2300
weighted avg       0.58      0.48      0.49      2300

test confusion matrix (rows = true, columns = predicted); the figure below draws the same matrix:
          pred dry  pred wet
true dry       594       936
true wet       260       510
false alarms (true dry, called wet) 936 · hits (true wet, called wet) 510 · false alarms per hit 1.84 · misses 260 · correct rejections 594
break-even: saying 'wetter' on these calls pays only if a false alarm costs less than hits / false alarms = 0.54 of a hit's value
always-wet's break-even on the same winters, for comparison: base rate / (1 − base rate) = 0.50
always-dry  precision 0.000  recall 0.000  wet-call share 0.000  accuracy 0.665
always-wet  precision 0.335  recall 1.000  wet-call share 1.000  accuracy 0.335
nino-sign   precision 0.327  recall 0.484  wet-call share 0.496  accuracy 0.494
accuracy, final minus always-dry: -0.185 · final minus nino-sign: -0.014
boosting@base-rate: precision − base rate  +0.018   95% interval over test members [+0.006, +0.031]  →  above no skill
boosting@base-rate: AP − base rate         +0.022   95% interval over test members [-0.004, +0.052]  →  NOT distinguishable from no skill
The final model's confusion matrix on the held-out test members: true dry and wet rows against predicted dry and wet columns, counts in each cell.
wet rate by TRAINING decile of the autumn Niño 3.4 anomaly, test members (base rate 0.335):
                     wet_rate    n  binomial_se  (rate - base) / se
nino34_anom bin (K)                                                
(-inf, -1.774]          0.296  216        0.031              -1.239
(-1.774, -1.137]        0.363  251        0.030               0.915
(-1.137, -0.726]        0.349  229        0.032               0.462
(-0.726, -0.366]        0.359  209        0.033               0.725
(-0.366, -0.00268]      0.339  254        0.030               0.128
(-0.00268, 0.364]       0.363  245        0.031               0.927
(0.364, 0.738]          0.366  235        0.031               0.992
(0.738, 1.167]          0.306  222        0.031              -0.920
(1.167, 1.743]          0.307  192        0.033              -0.826
(1.743, inf]            0.291  247        0.029              -1.497
chi-square test of wet against decile, test members: chi2 = 8.5, dof = 9, p = 0.48
test members, two extreme bins: wet rate 0.294 ± 0.021 (binomial SE, n = 463)
test members, eight middle bins: wet rate 0.345 ± 0.011 (binomial SE, n = 1837)
extremes minus middle: -0.051 ± 0.024 (binomial SEs treat winters as independent: untested for clustering within members)

The shape, on the test members. Compare the table (training edges) with chapter 2’s; a chi-square p well above 0.05 means the test bins alone are not distinguishable from chance. The last three lines pool the two extreme bins against the eight middle ones: a post hoc contrast, chosen after the table was seen, with binomial errors untested for clustering within members.

Justify the decision

Unidata’s closing instruction: “No matter your final decision, the most important aspect is your ability to justify it using data and a robust evaluation.”

The costlier error (chapter 4’s assumption) is a false alarm: a statistically wetter line in a briefing before a dry winter. Per the break-even line, saying “wetter” pays only if a false alarm costs less than the printed fraction of a hit; the always-wet's break-even line gives the same for calling every winter wet, and the gap is all the model adds. In this model world, an office that weighs a false alarm as heavily as a hit would gain nothing over CPC’s “equal chances”. The precision edge (the interval line) is small and provisional, and chapter 7’s test does not replicate it.

The justification, in three labelled parts:

  1. Does it deliver? The interval, false-alarm and break-even lines.

  2. If not, say so plainly. The answer is the base rate; the briefing stays at “equal chances”.

  3. The next change, and its cost. A new season or box: a parameter edit and a rebuild (chapter 1). A new input: a new box mean in derive_member_winters and a rebuild (chapter 2). A snowfall target (PRECSC + PRECSL): one more derivation.

The result’s shape

The straight-line relation is indistinguishable from zero (chapter 2’s standard errors line). Training members’ wet rate varies between bins, extremes drier than the middle (chapter 2’s decile table). On the test members the chi-square line does not confirm it; the extremes minus middle line shows extremes drier again, a post hoc description, not a test. In chapter 7’s future winters only the coldest bin is beyond 2 SE, one of ten (its decile table, a protocol secondary outcome; omnibus p = 0.32; read post hoc).

The limits

  1. A model world. CESM2 scored against CESM2, never observations.

  2. CESM2’s own ENSO and teleconnection, biases included.

  3. A ~1° grid, smoothing the orography Stagge et al. (2023) find amplifies the ENSO signal on western slopes.

  4. The season. DJF holds only February of the late winter and spring NWS Boulder stresses for El Niño east of the Divide; its La Niña-dry statement for southwest and eastern Colorado covers the entire cold season.

  5. Total precipitation (PRECC + PRECL), not snowfall, and a wet-only target: the coldest decile’s dry signal (above) is one a classifier of wet winters cannot state as a “drier” call; a dry-tercile target is the next change to try.

  6. One forced-response curve for both forcing halves, so a half-specific forced path is absorbed, not tested. Rodgers et al. (2021, §2.3) report that the halves’ different biomass-burning forcing has “a discernible impact on large-scale climate”, including “tropical Pacific warming”, around 1990–2010; this cookbook does not test whether that shifts the Niño 3.4 input in those years.

  7. A box that crosses the Divide: about half mountain, half plains. NWS Boulder (the north-central mountains, wetter under La Niña) and Stagge et al.'s Fig. 1b (the central mountains) give part of the west column the reverse of NWS Boulder’s east-of-Divide sign.

  8. Not a blind test (the top of this chapter).

Summary

The spine, end to end: framing, data, the forced response removed, a member split, a ladder, corrected paired trials, and a provisional held-out test read against the cost of a false alarm. Chapter 7’s future test (protocol fixed before the run, self-attested) does not replicate the edge. The figure maps each step to its chapter.

A row of eight gold boxes joined by arrows, reading framing, data, split, train, validate, refine, test, justify; under each step's name is the chapter that took it (chapter 1; chapters 1 and 2; chapter 3; chapter 4 for train and validate; chapters 4 and 5; chapter 6 for test and justify) and below the box the failure the step guards against.

What’s next?

Chapter 7 runs the test this chapter cannot: the same members’ SSP3-7.0 winters, under a protocol fixed before the scored run (self-attested; no external timestamp). Further ML in Pythia: the scikit-learn Argo, xbatcher ML and Landsat ML cookbooks. Optional: the ncar-ml-readiness-course repository keeps this ladder and adds a small neural network.

Resources and references

ResourceWhere it bearsLicence
Grover, M., & Banihirwe, A. (2021). NCAR CESM2 Large Ensemble Cloud-Optimized Dataset. NSF NCAR CISL. doi:10.26024/y48t-q717the dataset (required citation)UCAR Data Terms of Use
Rodgers, K. B. et al. (2021). Earth System Dynamics 12, 1393–1411. doi:10.5194/esd-12-1393-2021the ensemble paper (required citation); §2.3 in limit 6CC BY 4.0
Stagge, J. H. et al. (2023). Orographic amplification of El Niño teleconnections on winter precipitation across the Intermountain West of North America. Nature Water 1, 1016–1026. doi:10.1038/s44221-023-00163-9limit 3; the dipole and its two polesCC BY 4.0
NWS Pueblo (2025). Winter of 2025-2026 Outlook. https://www.weather.gov/media/pub/pdf/SC_SE_CO_Winter_2025_26_Outlook.pdfCPC’s “equal chances”US Government work
NWS Boulder (2020). La Niña and the Upcoming 2020-2021 Winter Season (contains 2010-era slides, e.g. “perhaps through the spring of 2011”). https://www.weather.gov/media/bou/LaNinaWinterOutlook_Sept20.pdfthe sign and its season; limit 7; limit 4US Government
NSF Unidata, Supervised Machine Learning Readiness (NSF award #2319979). https://github.com/Unidata/supervised-ml-readinessthe spine; the closing instructionApache-2.0
Project Pythia notebook template. https://foundations.projectpythia.org/appendix/templatethe shape of each chapterCC BY 4.0
scikit-learn User Guide, §12 Common pitfalls. https://scikit-learn.org/stable/common_pitfalls.htmlthe seed; transforms fit inside the splitBSD-3-Clause

Results based on the CESM2 Large Ensemble acknowledge the CESM2 Large Ensemble Community Project and supercomputing resources provided by the IBS Center for Climate Physics in South Korea. This cookbook was self-funded and has not been reviewed or sponsored by NSF NCAR or NSF Unidata.