Preserve the supervised-YOLO baseline training record (#51) - #77
Conversation
The supervised-YOLO baseline runs (issue #51) trained on Hyak, whose outputs live on /gscratch/scrubbed and auto-purge after ~21 idle days. Capture the perishable, reproducible record in git before it's lost, following the repo's existing convention (curated small-text results tracked; bulk/binary/regenerable artifacts stay out — see .gitignore). Adds scripts/model_comparison/yolo_baseline/: - run_yolo_train.slurm + hyak_yolo_runbook.sh: the training code (previously only on the cluster), so the runs are reproducible. - runs/<config>/{results.csv,args.yaml}: per-epoch curves + resolved config for all six configs (y11x_tiles has args only — it was dropped before epoch 1). - README.md: config grid, metrics table, the training-instability finding, and a provenance block (toolchain, dataset + prep params, hyperparameters, Slurm job IDs, dates). Finding: the two YOLO11 pano configs (y11x_pano, y11l_pano) collapsed — val mAP fell to ~0 for 4+ epochs while training loss stayed healthy and no NaN/AMP error occurred, a validation-side collapse consistent with BatchNorm/EMA instability at small physical batch (2-4) and high input resolution (1280). YOLO26 and the tiles runs were unaffected. Weights are intentionally not committed; healthy best.pt files go to durable external storage (URL to be recorded in the README). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per the "record scientific progress in GitHub" standing rule (CLAUDE.md): make the in-flight supervised baseline discoverable from docs/model_comparison.md rather than only in the sub-directory README. Adds a short "supervised baseline in progress" note to the coverage-matrix section — the collapse (negative result) and the dropped/pending configs (gaps) are stated explicitly so the baseline's absence from the results tables reads as "not yet run", not "withheld". Also flags in the README that the launcher/runbook copies are as-run snapshots to be reconciled with the canonical Phase-0 harness (#51) when it merges. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The architecture-vs-data ablation for issue #51: does a generic detector trained on the RampNet dataset also beat the zero-shot field, or is RampNet's keypoint architecture doing the work? - YoloDetector + yolo_results_to_boxes in detectors.py, plus the `yolo` branch in build_detector. Identity is the weights file stem, so the detection cache key is machine-independent; signature() hashes the weights bytes, so a retrain busts the cache. It emits scored boxes, so YOLO gets AP, PR curves and --sweep like the other open detectors. - compare.py: --yolo-model / --yolo-conf (0.05 floor) / --yolo-iou / --yolo-imgsz. requirements-vlm.txt: ultralytics. - prepare_yolo_dataset.py: tiles+pano dataset builder with pluggable box-size strategies and deterministic background thinning. - run_yolo_{data,prep,train}.slurm and hyak_yolo_runbook.sh (repo root, beside hyak_qwen_runbook.sh). - +10 tests. The training record these scripts produced is PR #77, kept separate so this PR is reviewable as code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Heads-up from #76 (the code half of #51), which was opened concurrently — the two This PR adds
The difference is display-only and cannot affect the recorded runs, so the record Suggested resolution for whichever merges second: keep the canonical copies, drop |
- Config table: record the as-run batches from args.yaml (y11x_tiles 3->12 across its two attempts, y26_tiles 6) -- batch is the load-bearing variable in the collapse hypothesis, so the table must be exact - Provenance: box-size corrected to pitch/1.8m per run_yolo_prep.slurm's as-run defaults, with a TODO to confirm from the klone prep log before scratch purges; add y11x_tiles's inferred job ID 37745359 - Drop the run_yolo_train.slurm / hyak_yolo_runbook.sh snapshots: the canonical copies land via #76 (launcher byte-identical; runbook drift was display-only, documented in #76). Removes the two-live-copies trap at merge time. - .gitignore: enforce the stated weights-out policy structurally (*.pt, *.pth) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fresh per-epoch data from the live Hyak runs falsifies two claims this record previously made, and the correction changes what should happen next. What was wrong: - "YOLO26 and the tiles configs trained cleanly" — they did not. All five remaining configs show the same collapse; the tiles runs were simply only two epochs into it when the record was written. - "Small-batch BatchNorm/EMA instability" — refuted by the grid itself. y11l_pano and y26_pano share batch 4 and imgsz 1280 and both collapsed, then both recovered. Batch spans 2/4/6 and imgsz 1024/1280 with no separation between healthy and sick. - "The collapsed runs hold only a non-reportable epoch-1 pretrained artifact, not worth keeping" — wrong on both counts. By epoch 1 the model has trained on all 150k images; the score is real. Those best.pt files are genuine best-val checkpoints and currently the only supervised baseline we have. What the data actually shows: validation mAP peaks at epoch 1, collapses at epoch 3, and recovers as the LR decays, in every config. Epoch 3 is exactly where the warmup ramp peaks (lr/pg0 0.010 -> 0.029, warmup_epochs=3). Training loss falls straight through the collapse while val cls_loss explodes 1.2 -> 8.2, with no NaN or AMP error — an optimization instability, not a crash or a data fault. The ckpt preemptions are scattered across epochs 2-13 and do not line up with it. optimizer=auto resolves to MuSGD(lr=0.01, momentum=0.9) in every job. So the clean test is a lower peak LR or longer warmup, not a larger batch — which is what #70 currently proposes. Adds plot_training_curves.py and four figures. The script reads only the committed results.csv files, so every figure regenerates from a clean checkout with no GPU, network, or checkpoints. Recorded per the "record scientific progress in GitHub" rule: the runs live on /gscratch/scrubbed, which auto-purges. Refs #51, #70, #71, #72. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Runbook: default ACCOUNT to ckpt-makelab (run_yolo_train.slurm pins the ckpt partition, which the old gpu-l40s default cannot submit to) and pin per-config BATCH in the train stage -- unpinned, jobs ran batch=-1 (auto), defeating the identical-LR-schedule rationale the .slurm header states - Runbook: align BOX_SIZE default with the as-run prep (pitch, ramp 1.8m, per run_yolo_prep.slurm) and point the multi-hour data/prep stages at their compute-node sbatch wrappers (login nodes reap heavy processes) - prepare_yolo_dataset.py: stamp the full prep config into data.yaml as comments -- box size et al. are train-only knobs no downstream args.yaml records, and exactly that gap made the #77 provenance question unanswerable from disk; regression test added (188 pass) - prepare_yolo_dataset.py: render each overlay view once, not twice; --overlay-n help now says PER SPLIT - detectors.py: hoist the hashlib import to module top Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Review fixes pushed in 562277a:
Data cross-check during review: every number in the status table matched the committed CSVs at snapshot time (epoch counts, ep1 values, current mAP50, the P≈0.94/R≈0.03 flicker, the 4 straight literal-0 epochs, the train-loss trends). One observation about collapse timing is on #70. 🤖 Generated with Claude Code |
Merging the canonical YOLO harness code. Its `scripts/model_comparison/run_yolo_train.slurm` and repo-root `hyak_yolo_runbook.sh` are the copies of record; the duplicate snapshots under `yolo_baseline/` are removed by #77, which lands next.
- Box-size: pitch + ramp 1.8m CONFIRMED from the session run notes (prep job 37677130, 2026-07-25; overlay QA rejected fixed:0.03, gps fell back on 169/200 smoke panos; output counts verified on scratch) -- removes the TODO(confirm) added in 562277a - y11x_tiles job IDs now exact: 37745359 original + 37809205 batch-12 resubmit; job<->config map was log-verified during the 2026-07-27 preemption check, not inferred Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Follow-up: the box-size confirmation flagged above is resolved without needing the klone log — the session run notes record it definitively (prep job 37677130, 2026-07-25: 🤖 Generated with Claude Code |
What
Preserves the supervised-YOLO baseline experiment (issue #51) as a durable,
reproducible record in the repo, and surfaces its in-flight status in the central
results doc.
Adds
scripts/model_comparison/yolo_baseline/:README.md— config grid, the training-instability finding, and a provenance block(toolchain, dataset + prep params, hyperparameters, Slurm job IDs, dates).
runs/<config>/{results.csv,args.yaml}— per-epoch curves + resolved config for all sixconfigs (
y11x_tileshasargs.yamlonly — it was dropped before epoch 1).plot_training_curves.py+figures/*.png— four diagnostic figures, regenerable fromthe committed CSVs alone (CPU-only, no network, no checkpoints).
Plus a "supervised baseline in progress" note in
docs/model_comparison.mdso thebaseline's absence from the results tables reads as not yet run, not withheld.
Why
Per the "record scientific progress in GitHub" standing rule (CLAUDE.md): the runs'
outputs live on
/gscratch/scrubbed, which auto-purges after ~21 idle days. This capturesthe perishable record before it's lost, following the repo convention (curated small-text
results tracked; weights/logs stay out).
The finding — and a correction to an earlier version of this PR
Fresh per-epoch data pulled from the live runs falsified three claims this branch
previously carried. They are corrected in the record, and the correction changes what
should happen next:
y11l_panoandy26_panoshare batch 4 / imgsz 1280 and both collapsed, then both recovered. Batch spans 2/4/6 and imgsz 1024/1280 with no separation.best.ptfiles are genuine best-val checkpoints and currently the only supervised baseline we have.What actually happens: validation mAP peaks at epoch 1, collapses at epoch 3, and
recovers as the LR decays — in every config. Epoch 3 is exactly where the warmup ramp
peaks (
lr/pg00.010 → 0.029,warmup_epochs=3). Training loss falls straight throughthe collapse while val
cls_lossexplodes 1.2 → 8.2, with no NaN or AMP error. The ckptpreemptions are scattered across epochs 2–13 and do not line up with it.
optimizer=autoresolves to
MuSGD(lr=0.01, momentum=0.9)in every job.So the clean test is a lower peak LR or longer warmup, not a larger batch — which is
what #70 currently proposes. Worth re-scoping before that rerun burns another week.
The failure signature is a recall collapse at sustained high precision: the model stops
firing rather than starting to guess. A checkpoint caught inside the dip would understate
recall catastrophically.
Overlap with #76 — resolved
#76 (merged) carries the canonical training code at
scripts/model_comparison/run_yolo_train.slurmand the repo-root
hyak_yolo_runbook.sh. This branch's duplicate snapshots underyolo_baseline/are deleted here, so merging leaves exactly one copy of each. Theprovenance those snapshots preserved is in git history.
Scope / notes for review
results.csvvalues are the internal YOLOval-split proxy (training health), not the reported baseline. Benchmark eval is pending, and
is now unblocked: every run's
best.ptis already on disk.*.pt/*.pthnow gitignored). The README has a TODO for thedurable URL.
relative to a stable schedule, and the README says so.
Related: #51 (parent), #70, #71, #72.
🤖 Generated with Claude Code