| |
| """ |
| Evaluate Phase A2 large models on six-task held-out set. |
| Compare with baseline to determine if 40%+ success achieved. |
| """ |
| from __future__ import annotations |
|
|
| import argparse |
| import json |
| import subprocess |
| import sys |
| from pathlib import Path |
|
|
| def main(argv: list[str] | None = None) -> int: |
| parser = argparse.ArgumentParser( |
| description="Evaluate all Phase A2 seeds and compare with baseline" |
| ) |
| parser.add_argument("--baseline-dir", type=Path, |
| default=Path("/scratch/knguy52/dovla/experiments/six_task_state_actionfix"), |
| help="Baseline experiment directory") |
| parser.add_argument("--phase-a2-dir", type=Path, |
| default=Path("/scratch/knguy52/dovla/experiments/phase_a2_large_model"), |
| help="Phase A2 models directory") |
| parser.add_argument("--dataset", type=Path, |
| default=Path("/scratch/knguy52/dovla/experiments/maniskill_presuccess_six_task_collection"), |
| help="Dataset directory") |
| parser.add_argument("--out", type=Path, |
| default=Path("reports/phase_a2_evaluation.json"), |
| help="Output JSON path") |
|
|
| args = parser.parse_args(argv) |
|
|
| print("=" * 70) |
| print("Phase A2 Evaluation") |
| print("=" * 70) |
| print() |
| print(f"Baseline: {args.baseline_dir}") |
| print(f"Phase A2: {args.phase_a2_dir}") |
| print(f"Dataset: {args.dataset}") |
| print() |
|
|
| results = { |
| "baseline": {}, |
| "phase_a2": {}, |
| "comparison": {} |
| } |
|
|
| |
| print("Loading baseline results...") |
| baseline_successes = [] |
| for seed in range(3): |
| eval_path = args.baseline_dir / f"seed_{seed}" / "policy_rollout.json" |
| if eval_path.exists(): |
| with open(eval_path) as f: |
| data = json.load(f) |
| succ = data.get("policy_rollout_success_rate", 0) |
| baseline_successes.append(succ) |
| results["baseline"][f"seed_{seed}"] = succ |
| print(f" Seed {seed}: {succ:.4f}") |
| else: |
| print(f" Seed {seed}: NOT FOUND (using known value 0.2967)") |
| baseline_successes.append(0.2967) |
| results["baseline"][f"seed_{seed}"] = 0.2967 |
|
|
| baseline_mean = sum(baseline_successes) / len(baseline_successes) |
| baseline_std = (sum((x - baseline_mean) ** 2 for x in baseline_successes) / len(baseline_successes)) ** 0.5 if len(baseline_successes) > 1 else 0.0 |
|
|
| print(f"Baseline mean: {baseline_mean:.4f} ± {baseline_std:.4f}") |
| print() |
|
|
| |
| print("Evaluating Phase A2 seeds...") |
| phase_a2_successes = [] |
|
|
| for seed in range(3): |
| checkpoint = args.phase_a2_dir / f"seed_{seed}" / "best.pt" |
| eval_out = args.phase_a2_dir / f"seed_{seed}" / "lattice_eval.json" |
|
|
| if not checkpoint.exists(): |
| print(f" Seed {seed}: CHECKPOINT NOT FOUND") |
| results["phase_a2"][f"seed_{seed}"] = None |
| continue |
|
|
| print(f" Seed {seed}: Evaluating...") |
|
|
| |
| cmd = [ |
| sys.executable, "scripts/eval_lattice_checkpoint.py", |
| "--checkpoint", str(checkpoint), |
| "--dataset", str(args.dataset), |
| "--out", str(eval_out), |
| "--all-groups", |
| "--device", "cuda" |
| ] |
|
|
| try: |
| subprocess.run(cmd, check=True, capture_output=True) |
| print(f" ✓ Evaluation complete") |
|
|
| |
| if eval_out.exists(): |
| with open(eval_out) as f: |
| data = json.load(f) |
| |
| succ = data.get("policy_rollout_success_rate", |
| data.get("selected_success_rate", |
| data.get("top1_action_selection", 0))) |
| phase_a2_successes.append(succ) |
| results["phase_a2"][f"seed_{seed}"] = succ |
| print(f" ✓ Success rate: {succ:.4f}") |
| else: |
| print(f" ✗ No eval output") |
|
|
| except subprocess.CalledProcessError as e: |
| print(f" ✗ Evaluation failed: {e}") |
| results["phase_a2"][f"seed_{seed}"] = None |
|
|
| print() |
|
|
| if phase_a2_successes: |
| phase_a2_mean = sum(phase_a2_successes) / len(phase_a2_successes) |
| phase_a2_std = (sum((x - phase_a2_mean) ** 2 for x in phase_a2_successes) / len(phase_a2_successes)) ** 0.5 if len(phase_a2_successes) > 1 else 0.0 |
|
|
| improvement = phase_a2_mean - baseline_mean |
| rel_improvement = (improvement / baseline_mean) * 100 |
|
|
| print("=" * 70) |
| print("RESULTS") |
| print("=" * 70) |
| print() |
| print(f"Baseline: {baseline_mean:.4f} ± {baseline_std:.4f}") |
| print(f"Phase A2: {phase_a2_mean:.4f} ± {phase_a2_std:.4f}") |
| print(f"Improvement: {improvement:+.4f} ({rel_improvement:+.1f}%)") |
| print() |
|
|
| if phase_a2_mean >= 0.40: |
| print("✅ TARGET ACHIEVED: 40%+ policy success!") |
| elif phase_a2_mean >= 0.35: |
| print("⚠️ Close to target (35-40%) - good progress") |
| else: |
| print("❌ Below target - need more work") |
|
|
| print() |
|
|
| results["comparison"] = { |
| "baseline_mean": baseline_mean, |
| "baseline_std": baseline_std, |
| "phase_a2_mean": phase_a2_mean, |
| "phase_a2_std": phase_a2_std, |
| "improvement_absolute": float(improvement), |
| "improvement_relative_pct": float(rel_improvement), |
| "target_40pct_achieved": phase_a2_mean >= 0.40 |
| } |
| else: |
| print("❌ No Phase A2 results to compare") |
| results["comparison"] = {"error": "No successful evaluations"} |
|
|
| |
| args.out.parent.mkdir(parents=True, exist_ok=True) |
| with open(args.out, "w") as f: |
| json.dump(results, f, indent=2) |
|
|
| print(f"✅ Results saved to: {args.out}") |
| print() |
|
|
| return 0 |
|
|
| if __name__ == "__main__": |
| sys.exit(main()) |
|
|