added better memory caching, multithreaded processing, cleanup scripts dir
This commit is contained in:
@@ -1287,7 +1287,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 3a) No crop — original full-size images\n",
|
||||
"!python scripts/basic_analysis/compare_hypertower_modes.py \\\n",
|
||||
"!python scripts/main/v2/multirun_hypertower.py \\\n",
|
||||
" --tower-modes single ensemble \\\n",
|
||||
" --eval-modes binary multiclass \\\n",
|
||||
" --epochs 40 --n-splits 5 \\\n",
|
||||
@@ -1305,7 +1305,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 3b) GT crop — expert segmentation masks crop the optic disc region\n",
|
||||
"!python scripts/basic_analysis/compare_hypertower_modes.py \\\n",
|
||||
"!python scripts/main/v2/multirun_hypertower.py \\\n",
|
||||
" --tower-modes single ensemble \\\n",
|
||||
" --eval-modes binary multiclass \\\n",
|
||||
" --epochs 40 --n-splits 5 \\\n",
|
||||
@@ -1323,7 +1323,7 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# 3c) UNet crop — trained segmenter crops the optic disc region\n",
|
||||
"!python scripts/basic_analysis/compare_hypertower_modes.py \\\n",
|
||||
"!python scripts/main/v2/multirun_hypertower.py \\\n",
|
||||
" --tower-modes single ensemble \\\n",
|
||||
" --eval-modes binary multiclass \\\n",
|
||||
" --epochs 40 --n-splits 5 \\\n",
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Thin CLI wrapper that runs V2 hypertower modes sequentially."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
if str(REPO_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(REPO_ROOT))
|
||||
|
||||
from classes.v2.v2_hypertower import V2HyperTower
|
||||
|
||||
|
||||
def parse_args():
|
||||
ap = argparse.ArgumentParser(
|
||||
description="Run selected eval/tower mode combinations sequentially."
|
||||
)
|
||||
ap.add_argument(
|
||||
"--eval-modes",
|
||||
nargs="+",
|
||||
choices=["binary", "multiclass"],
|
||||
default=["binary", "multiclass"],
|
||||
)
|
||||
ap.add_argument(
|
||||
"--tower-modes",
|
||||
nargs="+",
|
||||
choices=["single", "ensemble", "bilateral", "classic"],
|
||||
default=["single", "ensemble", "bilateral"],
|
||||
)
|
||||
return ap.parse_known_args()
|
||||
|
||||
|
||||
def main():
|
||||
seq_args, remaining = parse_args()
|
||||
base_parser = V2HyperTower.build_parser()
|
||||
first_run = True
|
||||
for eval_mode in seq_args.eval_modes:
|
||||
for tower_mode in seq_args.tower_modes:
|
||||
tower_mode = "single" if tower_mode == "classic" else tower_mode
|
||||
cli = list(remaining) + ["--eval-mode", eval_mode, "--tower-mode", tower_mode]
|
||||
# Clear cache only on the first run; reuse it for all subsequent runs.
|
||||
if not first_run:
|
||||
cli.append("--persist-img-crop-cache")
|
||||
args = base_parser.parse_args(cli)
|
||||
# Skip if this mode is already fully complete.
|
||||
if args.run_name:
|
||||
tm_dir = Path(args.output_root) / args.run_name / eval_mode / tower_mode
|
||||
if (tm_dir / "summary.json").exists():
|
||||
print(f"[compare] {eval_mode}:{tower_mode} already complete — skipping.")
|
||||
first_run = False # treat as done so cache is preserved for later runs
|
||||
continue
|
||||
V2HyperTower(args).run()
|
||||
first_run = False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Binary runs v2.2 (4 total):
|
||||
# UNet crop: single | fused head
|
||||
# GT crop: single | fused head
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
MANIFEST="manifest.csv"
|
||||
UNET_WEIGHTS="models/v2/refuge/segmentation/per_image/best.pt"
|
||||
|
||||
COMMON=(
|
||||
--epochs 40
|
||||
--n-splits 5
|
||||
--batch-size 8
|
||||
--backbone refugelike
|
||||
--eval-mode binary
|
||||
--single-warmup-tower-epochs 4
|
||||
--single-warmup-fused-epochs 4
|
||||
--img-crop-manifest "$MANIFEST"
|
||||
)
|
||||
|
||||
UNET_CROP=(
|
||||
--img-crop-weights "$UNET_WEIGHTS"
|
||||
)
|
||||
|
||||
GT_CROP=(
|
||||
--img-crop-gt
|
||||
)
|
||||
|
||||
# ── UNet crop ────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[1/4] UNet crop — binary, single..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${UNET_CROP[@]}" \
|
||||
--tower-mode single \
|
||||
--run-name v2.2_single_binary_unet_40ep_5fold
|
||||
|
||||
echo "[2/4] UNet crop — binary, ensemble + fused head..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${UNET_CROP[@]}" \
|
||||
--tower-mode ensemble \
|
||||
--fused-head --fusion-epochs 20 \
|
||||
--run-name v2.2_fused_binary_unet_40ep_5fold
|
||||
|
||||
# ── GT crop ──────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[3/4] GT crop — binary, single..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${GT_CROP[@]}" \
|
||||
--tower-mode single \
|
||||
--run-name v2.2_single_binary_gt_40ep_5fold
|
||||
|
||||
echo "[4/4] GT crop — binary, ensemble + fused head..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${GT_CROP[@]}" \
|
||||
--tower-mode ensemble \
|
||||
--fused-head --fusion-epochs 20 \
|
||||
--run-name v2.2_fused_binary_gt_40ep_5fold
|
||||
|
||||
echo "Binary v2.2 runs complete."
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Image-only runs v2.21 (6 total):
|
||||
# No crop: binary | multiclass
|
||||
# GT crop: binary | multiclass
|
||||
# UNet crop: binary | multiclass
|
||||
#
|
||||
# Purpose: isolate the effect of ROI cropping at the single-CNN level,
|
||||
# without any MD tower contribution (bridge-mode=image_only).
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
MANIFEST="manifest.csv"
|
||||
UNET_WEIGHTS="models/v2/refuge/segmentation/per_image/best.pt"
|
||||
|
||||
COMMON=(
|
||||
--epochs 40
|
||||
--n-splits 5
|
||||
--batch-size 8
|
||||
--backbone refugelike
|
||||
--tower-mode single
|
||||
--bridge-mode image_only
|
||||
--single-warmup-tower-epochs 4
|
||||
--single-warmup-fused-epochs 0
|
||||
--img-crop-manifest "$MANIFEST"
|
||||
)
|
||||
|
||||
# ── No crop ──────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[1/6] No crop — binary, image-only..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" --eval-mode binary \
|
||||
--run-name v2.21_imgonly_binary_nocrop_40ep_5fold
|
||||
|
||||
echo "[2/6] No crop — multiclass, image-only..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" --eval-mode multiclass \
|
||||
--run-name v2.21_imgonly_multiclass_nocrop_40ep_5fold
|
||||
|
||||
# ── GT crop ──────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[3/6] GT crop — binary, image-only..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" --eval-mode binary --img-crop-gt \
|
||||
--run-name v2.21_imgonly_binary_gt_40ep_5fold
|
||||
|
||||
echo "[4/6] GT crop — multiclass, image-only..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" --eval-mode multiclass --img-crop-gt \
|
||||
--run-name v2.21_imgonly_multiclass_gt_40ep_5fold
|
||||
|
||||
# ── UNet crop ────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[5/6] UNet crop — binary, image-only..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" --eval-mode binary \
|
||||
--img-crop-weights "$UNET_WEIGHTS" \
|
||||
--run-name v2.21_imgonly_binary_unet_40ep_5fold
|
||||
|
||||
echo "[6/6] UNet crop — multiclass, image-only..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" --eval-mode multiclass \
|
||||
--img-crop-weights "$UNET_WEIGHTS" \
|
||||
--run-name v2.21_imgonly_multiclass_unet_40ep_5fold
|
||||
|
||||
echo "Image-only v2.21 runs complete."
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Multiclass runs v2.2 (4 total):
|
||||
# UNet crop: single | fused head
|
||||
# GT crop: single | fused head
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
MANIFEST="manifest.csv"
|
||||
UNET_WEIGHTS="models/v2/refuge/segmentation/per_image/best.pt"
|
||||
|
||||
COMMON=(
|
||||
--epochs 40
|
||||
--n-splits 5
|
||||
--batch-size 8
|
||||
--backbone refugelike
|
||||
--eval-mode multiclass
|
||||
--single-warmup-tower-epochs 4
|
||||
--single-warmup-fused-epochs 4
|
||||
--img-crop-manifest "$MANIFEST"
|
||||
)
|
||||
|
||||
UNET_CROP=(
|
||||
--img-crop-weights "$UNET_WEIGHTS"
|
||||
)
|
||||
|
||||
GT_CROP=(
|
||||
--img-crop-gt
|
||||
)
|
||||
|
||||
# ── UNet crop ────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[1/4] UNet crop — multiclass, single..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${UNET_CROP[@]}" \
|
||||
--tower-mode single \
|
||||
--run-name v2.2_single_multiclass_unet_40ep_5fold
|
||||
|
||||
echo "[2/4] UNet crop — multiclass, ensemble + fused head..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${UNET_CROP[@]}" \
|
||||
--tower-mode ensemble \
|
||||
--fused-head --fusion-epochs 20 \
|
||||
--run-name v2.2_fused_multiclass_unet_40ep_5fold
|
||||
|
||||
# ── GT crop ──────────────────────────────────────────────────────────────────
|
||||
|
||||
echo "[3/4] GT crop — multiclass, single..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${GT_CROP[@]}" \
|
||||
--tower-mode single \
|
||||
--run-name v2.2_single_multiclass_gt_40ep_5fold
|
||||
|
||||
echo "[4/4] GT crop — multiclass, ensemble + fused head..."
|
||||
python3 scripts/main/v2/run_multifold_v2.py \
|
||||
"${COMMON[@]}" "${GT_CROP[@]}" \
|
||||
--tower-mode ensemble \
|
||||
--fused-head --fusion-epochs 20 \
|
||||
--run-name v2.2_fused_multiclass_gt_40ep_5fold
|
||||
|
||||
echo "Multiclass v2.2 runs complete."
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
echo "=== v2.3 ensemble binary nocrop ==="
|
||||
python scripts/basic_analysis/compare_hypertower_modes.py \
|
||||
--tower-modes ensemble --eval-modes binary \
|
||||
--epochs 40 --n-splits 5 \
|
||||
--backbone refugelike \
|
||||
--img-crop-manifest analysis_data/unet_manifest.csv \
|
||||
--run-name v2.3_ensemble_binary_nocrop
|
||||
|
||||
echo "=== v2.3 ensemble multiclass nocrop ==="
|
||||
python scripts/basic_analysis/compare_hypertower_modes.py \
|
||||
--tower-modes ensemble --eval-modes multiclass \
|
||||
--epochs 40 --n-splits 5 \
|
||||
--backbone refugelike \
|
||||
--img-crop-manifest analysis_data/unet_manifest.csv \
|
||||
--run-name v2.3_ensemble_multiclass_nocrop
|
||||
|
||||
echo "=== done ==="
|
||||
@@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
echo "=== v2.3 fused binary nocrop ==="
|
||||
python scripts/basic_analysis/compare_hypertower_modes.py \
|
||||
--tower-modes ensemble --eval-modes binary \
|
||||
--epochs 40 --n-splits 5 \
|
||||
--backbone refugelike \
|
||||
--img-crop-manifest analysis_data/unet_manifest.csv \
|
||||
--warmup-md-epochs 50 \
|
||||
--fused-head \
|
||||
--run-name v2.3_fused_binary_nocrop
|
||||
|
||||
echo "=== v2.3 fused multiclass nocrop ==="
|
||||
python scripts/basic_analysis/compare_hypertower_modes.py \
|
||||
--tower-modes ensemble --eval-modes multiclass \
|
||||
--epochs 40 --n-splits 5 \
|
||||
--backbone refugelike \
|
||||
--img-crop-manifest analysis_data/unet_manifest.csv \
|
||||
--warmup-md-epochs 50 \
|
||||
--fused-head \
|
||||
--run-name v2.3_fused_multiclass_nocrop
|
||||
|
||||
echo "=== done ==="
|
||||
Reference in New Issue
Block a user