Add new regression and ensemble experiment configurations for V2-M and OrthoBridge
- Introduced multiple regression experiment configurations targeting vf_md, including: - cd_solo_reg_set.json: CD tower only regression setup. - img_solo_reg_set.json: Image tower only regression setup. - reg_head_epoch_sweep.json: Baseline regression sweeps at different epochs (50, 75, 100). - reg_head_set.json: Various regression setups including baseline and OrthoBridge configurations. - single_eye_reg.json: Single-eye regression setup for worst-eye aggregation analysis. - Added ensemble configurations for OrthoBridge with different inner bridges: - ortho_alts_ensemble.json: Ensemble tests with ConcatBridge, PairwiseAdditiveBridge, and GatedAdditiveBridge. - ortho_alts_tritower.json: Tritower tests with the same inner bridges. - Created V2-M specific configurations: - baseline_reg_nt50.json: Regression baseline with V2-M backbone. - geom_vec_gt.json and geom_vec_unet.json: Geometry vector injection experiments with V2-M. - single_l1_bridges.json: Single-eye ensemble experiments with various bridge types. - tritower_geom_gt.json: Tritower setup with GT contour-rasterized masks. - Promoted existing experiments to higher repetitions for robustness.
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
"""Shared loaders/aggregators for v4 figure scripts."""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[3]
|
||||
RESULTS_ROOT = REPO_ROOT / "v4" / "results" / "experiments"
|
||||
|
||||
|
||||
def summarise_run(run_path: Path, primary_hint: Optional[str] = None) -> Optional[dict]:
|
||||
"""Aggregate val/test primary-metric mean & std across reps for one run folder.
|
||||
|
||||
Returns dict with n, val_mean, val_std, test_mean, test_std, metric_name, or None if no reps."""
|
||||
val, test = [], []
|
||||
metric_name = primary_hint
|
||||
for rep in sorted(run_path.glob("rep*")):
|
||||
s = next(iter(rep.rglob("summary.json")), None)
|
||||
if not s:
|
||||
continue
|
||||
d = json.loads(s.read_text())
|
||||
pm = d.get("primary_metric") or metric_name or "auc"
|
||||
metric_name = metric_name or pm
|
||||
v = d.get(f"mean_val_{pm}")
|
||||
t = d.get(f"mean_test_{pm}")
|
||||
if v is None or t is None or not np.isfinite(v) or not np.isfinite(t):
|
||||
continue
|
||||
val.append(float(v)); test.append(float(t))
|
||||
if not val:
|
||||
return None
|
||||
return {
|
||||
"n": len(val),
|
||||
"metric": metric_name or "auc",
|
||||
"val_mean": float(np.mean(val)),
|
||||
"val_std": float(np.std(val)),
|
||||
"test_mean": float(np.mean(test)),
|
||||
"test_std": float(np.std(test)),
|
||||
"val_arr": np.array(val),
|
||||
"test_arr": np.array(test),
|
||||
}
|
||||
|
||||
|
||||
def summarise_many(name_to_path: dict[str, Path], primary_hint: Optional[str] = None) -> dict[str, Optional[dict]]:
|
||||
"""Apply summarise_run to a dict of labelled run folders."""
|
||||
return {label: summarise_run(p, primary_hint) for label, p in name_to_path.items()}
|
||||
|
||||
|
||||
def fmt_status(s: Optional[dict]) -> str:
|
||||
if s is None:
|
||||
return "pending"
|
||||
return f"n={s['n']:>2d} test={s['test_mean']:.4f}±{s['test_std']:.4f}"
|
||||
Reference in New Issue
Block a user