Skip to content

Add model_1702 comparison harness (6-class) - #49

Merged
aaTman merged 60 commits into
feat/2.0.0from
harness/aies1702-comparison
Aug 3, 2026
Merged

Add model_1702 comparison harness (6-class)#49
aaTman merged 60 commits into
feat/2.0.0from
harness/aies1702-comparison

Conversation

@aaTman

@aaTman aaTman commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a self-contained model_1702 comparison harness (src/fronts/model_1702/, configs/model_1702/, scripts/model_1702_*.sbatch, tests/model_1702/) for evaluating the legacy AIES FrontFinder model_1702 head-to-head against 2.0 checkpoints.
  • Keeps evaluate.py's predict_batches/accumulate_stats split, numpy vectorization optimizations in the TP/FP/TN/FN accumulation loop, and the TestVisualizationCallback OOM fix (loop over predict_on_batch instead of one model.predict() call).
  • This branch originally forked from feat/include-forming-dissipating-and-troughs, so it carried that branch's 9-class scheme (TROF/tropical-trough/instability-axis + forming/dissipating collapse) into every shared file it touched. That's been stripped back out — config.py, model.py, plot/plot.py, targets.py, their tests, and all schooner_*.yaml training configs now match feat/2.0.0 exactly (6 classes, no troughs, no forming/dissipating).

Test plan

  • pixi run pytest -q — 403 passed, 48 skipped, 1 pre-existing unrelated failure (ModuleNotFoundError: No module named 'wandb', also fails on stock feat/2.0.0 in this env)
  • git grep for trough/forming/dissipating terms across the tree returns nothing outside of unrelated word matches
  • Confirmed ModelConfig.n_classes == 6 and no config file has a >6-length class_weights/front_types list

🤖 Generated with Claude Code

aaTman and others added 30 commits July 2, 2026 19:14
Replace fractions_skill_score as the training objective with a proper
scoring rule: the MSE between observed and forecast neighborhood
fractions (FSS's numerator without the hedgeable skill-score
normalization), summed over 25/100/250 km tolerance scales. Zonal
windows widen by 1/cos(lat) so tolerance stays isotropic in km, and
domain edges use valid-cell normalization (no reflect or wrap; the
longitude strip ends are not adjacent). No sigmoid discretization,
which would break propriety.

The 25 km scale reproduces the old 1-pixel label dilation, so
front_dilation is removed from the dataset, evaluation, and configs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aaTman and others added 28 commits July 21, 2026 13:47
…-domain transfer

Adds ModelConfig.pretrained_weights_path/freeze_layer_prefixes and train.py helpers
to load a prior checkpoint's weights, reset input_normalization to the current run's
domain stats, and optionally freeze layers by name prefix before compiling. Includes
a schooner_train_full_pretrained_3d.yaml config wiring this up for a full-domain
fine-tune from a CONUS-trained checkpoint.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The full domain has no dryline labels because label coverage doesn't extend
there, not because drylines don't occur, so leaving that class weighted
would actively train the model toward "dryline never happens" and erode
what the CONUS checkpoint already learned for it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The eval config was never updated for the brier_conus_3d_comparison
3D U-Net: it was missing volume_inputs (defaulting to the flattened
2D path), listed the wrong variable set/order, and pointed at the
full-domain coordinates instead of the CONUS box the model trained on.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… add trough/tropical-trough/instability

Forming (CF-F..OF-F) and dissipating (CF-D..OF-D) front codes now collapse into
their parent front class instead of being dropped as background. Trough (TROF),
tropical trough (TT), and instability axis (INST) become new independent classes
6, 7, and 8, bringing the total to 9 (was 6: background + CF/WF/SF/OF/DL).

n_classes, class_weights, loss_class_weights, and front_types are updated across
all training/eval/pipeline configs. The CONUS->full-domain warm-start config keeps
skip_mismatch=True so the 6-class CONUS checkpoint's output layer is dropped and
the 3 new classes train from scratch alongside the rest of the fine-tuned decoder.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…lback

callbacks.py had its own local 5-class FRONT_TYPE_CLASS_INDEX that was
missed when the rest of the codebase (targets.py, evaluate.py, plot.py,
configs) was expanded to 9 classes. Training-time visualization images
and lite performance-diagram stats were silently excluding TROF/TT/INST.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add trough/tropical-trough/instability-axis to training-viz callback
…U per batch

model.predict() batches its forward passes internally but still accumulates every
batch's output into one GPU-resident tensor before returning. On full-CONUS-domain
training runs (large spatial extent x 200-timestep visualization subsample x
9 front classes), that accumulated buffer on top of training's already-resident
GPU memory reliably OOMs (observed crash: OOM in ConcatV2 inside
TestVisualizationCallback._predict at shape[200,320,960,9]).

Loop over predict_on_batch and move each batch to CPU immediately instead, so
only one batch's output is ever GPU-resident at a time.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fix GPU OOM in TestVisualizationCallback (stream predict to CPU per batch)
Runs the legacy AIES FrontFinder checkpoint (Keras 2.10 h5) through the 2.0
eval/plot machinery for a head-to-head against current models on identical
2019 test data:

- loader: patches the stored model_config (TFOpLambda squeeze -> LevelSqueeze,
  standard inbound-node format), rebuilds under Keras 3, loads weights by name
  with full weight-consumption verification (8,745,968 params, 4 softmax heads)
- legacy_formulas: verbatim numpy port of utils/variables.py@c59ac2b with
  docstring golden-value tests (derived.py diverges: Lv 2.501e6 vs 2.257e6)
- normalization: embedded min-max table, parity-tested against
  model_1702_properties.txt
- adapter: raw (batch, lat, lon, level, var) -> legacy normalization ->
  lon-major transpose -> sup1 head -> 6-to-9-class zero padding, matching
  evaluate.compute_stats' contract; ClassPaddingAdapter for 6-class baselines
- store: side icechunk store generation (surface+1000/950/900/850, legacy
  units) from Arraylake ERA5 or ARCO fallback, resume-safe batched writes
- run_eval: config-driven driver for both model kinds over full/land/ocean and
  the five office regions (with wrap-crossing longitude fix), writing
  evaluate-compatible stats_*.nc
- figures/compare: batch 4-panel rendering and cross-model max-CSI summary
  with out-of-domain footnotes

Zero core-module edits; verified end-to-end on the 2019-03-13 bomb cyclone
(coherent CF/WF/DL structures from a real ARCO ERA5 timestep).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fronts.aies1702.case_study renders multi-panel model_1702 prediction maps in
the paper's presentation: filled front-probability contours at 10% intervals
(CF/WF/SF/OF cmaps from fronts.plot), state-border backgrounds via
plot_background, yellow a)/b)/c) panel labels, and per-panel UTC captions.
Inputs are derived on the fly from Arraylake or ARCO ERA5 with the legacy
formulas and cached to NetCDF so repeat renders skip the fetch entirely.

Ships configs/aies1702/case_study_xmas2023.yaml reproducing the 2023
Christmas storm panels (00Z/12Z 26-27 Dec 2023); verified end-to-end locally
against the real checkpoint — panel structures match the paper's Fig. 14,
including the d-panel occlusion remnants over the UP of Michigan and the
Midwest called out in the text. Raw (uncalibrated) probabilities from ERA5
analysis vs the paper's calibrated GFS f000, noted in the figure title.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…script

The Arraylake earthmover-public ERA5 repo lacks the 950 and 900 hPa levels
model_1702 requires, so both generate configs now point at the anonymous
Google ARCO ERA5 zarr (no auth needed).

scripts/aies1702_comparison.sbatch runs the whole 2019 comparison in one job:
side-store generation (resume-safe), all five evaluations, figures, and the
comparison summary. Resubmit-safe — completed eval stages are skipped via
their final region's stats_derived marker file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The artifact under comparison is model_1702, so the package, tests, configs,
SLURM script, model_kind string, keras serialization package, render-test env
var (MODEL_1702_RENDER_TESTS), and all schooner paths now use model_1702.
No functional changes; 83 tests pass unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
harness/model_1702-comparison was branched from
feat/include-forming-dissipating-and-troughs, so every shared file it
touched carried that branch's 9-class scheme (TROF/TT/INST plus
forming/dissipating collapse) even though the actual model_1702
comparison harness itself never needed more than the original 6
classes. Reverts config.py, model.py, plot.py, targets.py, and the
schooner_*.yaml training configs to their feat/2.0.0 state; keeps the
callbacks.py predict_on_batch OOM fix and the evaluate.py
predict_batches/accumulate_stats split plus numpy optimizations, which
are unrelated to class count; and fixes the new model_1702/ package
(adapter.py, eval configs, tests) to assume 6 classes throughout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Resolves a conflict in evaluate.py by keeping both refactors: this
branch's compute_stats/predict_batches/accumulate_stats split and
feat/2.0.0's load_eval_arrays extraction.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

# Conflicts:
#	src/fronts/evaluate.py
@aaTman
aaTman merged commit d7867a9 into feat/2.0.0 Aug 3, 2026
@aaTman
aaTman deleted the harness/aies1702-comparison branch August 3, 2026 15:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant