longitudinal/BENCHMARKING.md

96 lines
No EOL
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Pipeline benchmark (A / B / C)
Benchmark of the three segmentation pipelines — A in-house Unet3D, B nnU-Net v2
(NTUHLPLTrainer), C MONAI UNet — driven by `scripts/benchmark_pipelines.py`
(DICE, training time, inference time, params, VRAM). Protocol details live in
the script docstring; this file records what has been run and what the machine
currently supports.
## Data chain status (2026-10-04)
The M6 labeled set was fully rebuilt on 2026-10-04 (see
`scripts/02_build_m6_dataset.py`): T1c fixed, best-of-ANTs
(`ants_rigid` / `ants_affine` / `ants_syn`, winner by Mattes MI), TV warped
onto the T1c grid with SMD+linear. After the repair pass:
- `data/manifests/m6_labeled.jsonl`: **1312** volumes (was 1094 pre-repair),
`m6_unlabeled.jsonl`: **229**
- all 1541 m6 processed volumes (`data/proc/<key>{,_label}.nii.gz`, 1mm
cropped/normalized) regenerated, 0 errors
- patient-level splits rebuilt (`scripts/05_build_splits.py`, seed 0):
**4200** labeled rows (ntuh + m6) → train 3570 / val 211 / test 419
volumes, 3893 subjects; unlabeled pool 13280
- tumor volume stats: median 3116 mm3, p95 24.8k, max 3.2M, zero_frac 0.12%
## Smoke run (2026-10-04)
Small/fast end-to-end check that all three pipelines run on the rebuilt data
(1 epoch, 24 train rows, 3 eval rows, TTA on, GPU 0):
```
python scripts/benchmark_pipelines.py --gpu 0 --max-rows 24 --nnu-cases 24 \
--max-eval-rows 3 --train-epochs 1 --out results/benchmark_pipelines_smoke.json
```
| pipeline | wall | s/epoch | tr VRAM | s/vol (TTA) | in VRAM | params | weights | dice (1 epoch) |
|---|---|---|---|---|---|---|---|---|
| A Unet3D(16, depth 4) | 17 s | 2.5 (8 steps) | 2.0 GB | 4.12 | 0.5 GB | 1.46 M | 5.9 MB | 0.0000 |
| B nnU-Net 3d_fullres | 285 s (incl. 83 s plan&preprocess, 4 s raw build) | 73.3 | 9.8 GB | 34.73 | 1.8 GB | 30.8 M | 246 MB | 0.0000 |
| C MONAI UNet(16→128) | 5 s | 2.5 (8 steps) | 1.7 GB | 0.33 | 0.5 GB | 1.19 M | 4.8 MB | 0.0005 |
DICE ≈ 0 is expected (models trained for a single epoch on 24 volumes); the
point of the run was validating the full chain — new m6 native/processed
manifests, split membership, B's `ntuh + m6_labeled` native join, nnU-Net
isolated dataset 221 build, inference + dice scoring. All three passed.
Eval rows for the smoke run were the first three `split_test` volumes (all
ntuh). Artifacts: `results/benchmark_pipelines_smoke.json`,
`_per_row.jsonl`, `_bench.png`.
### Environment fixes made during the check
- `monai` was missing from `longitudinal-313` (pipeline C failed with
ModuleNotFoundError) — installed `pip install monai==1.6.1 --no-deps`
(torch 2.14+cu126 untouched); `import monai` verified.
## Resuming training (`--resume`)
All three pipelines can continue from their latest benchmark checkpoint:
```
python scripts/benchmark_pipelines.py --pipelines "A B C" --resume \
--train-epochs 200 --nnu-skip-prep
```
- `--train-epochs` is the **total budget** (not epochs added). Each pipeline
trains from where its checkpoint left off up to that total.
- **A / C**: load `runs_bench/{A,C}/best.pt` (model + optimizer + scheduler
state — checkpoints written before 2026-10-04 carry model + epoch only and
fall back to fresh optimizer/scheduler) and run the remaining epochs; the
run is a no-op train (eval only) when the checkpoint already reached the
total.
- **B**: appends nnU-Net's `--c` flag (continue `fold_0` from
`checkpoint_latest.pth`, native optimizer + LR-schedule restore) and
`NNUNet_pl_EPOCHS = --train-epochs`. Pair with `--nnu-skip-prep` so the
preprocessed tree isn't `--clean`ed; the isolated Dataset221 is rebuilt
otherwise and a finished run's `checkpoint_latest.pth` is gone, so a
completed run + a bigger budget retrains B from scratch (interrupted runs
keep `checkpoint_latest.pth` and resume correctly).
- Verified 2026-10-04: A/C resumed epoch 1 → 3 (model restored, fresh
opt/sched for the old-format ckpt), re-run at 3/3 trained 0 epochs, B
continued from epoch 1 with LR restored mid-decay (0.00536 @ start of
epoch 2).
## Readiness notes for a full run
- Budget knobs: `--train-epochs` (default 100), `--max-rows` (default 80% of
split_train ≈ 2856 for A/C and for B's `--nnu-cases`), `--max-eval-rows`
(default 10% of split_test ≈ 42), `--no-tta`.
- `--skip-train` is only usable for **A** (`runs/round0/best.pt`, trained
2026-09-25 on the *previous* split — a few patients moved between
train/test in the rebuild, so its test dice carries a small leakage
caveat). No study checkpoints exist for B (Dataset210) or C
(`runs_monai/round0/best.pt`); they must be trained.
- GPUs: 3× 80 GB available; the benchmark uses one (`--gpu`).
- B's one-time cost scales with `--nnu-cases` (plan_and_preprocess ≈ 3.5 s/case
at 24 cases with 8 preprocess procs, plus training time at the planned
batch/patch).