| |
| """ |
| Evaluate all Phase A4 hyperparameter configs. |
| Find best configuration for achieving 40%+ success. |
| """ |
| 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 A4 hyperparameter configs" |
| ) |
| parser.add_argument("--config-dir", type=Path, |
| default=Path("/scratch/knguy52/dovla/experiments/phase_a4_hparam_sweep"), |
| help="Phase A4 configs 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_a4_results.json"), |
| help="Output JSON path") |
|
|
| args = parser.parse_args(argv) |
|
|
| print("=" * 70) |
| print("Phase A4 Hyperparameter Evaluation") |
| print("=" * 70) |
| print(f"Config dir: {args.config_dir}") |
| print(f"Dataset: {args.dataset}") |
| print() |
|
|
| configs = sorted([d for d in args.config_dir.iterdir() if d.is_dir()]) |
| print(f"Found {len(configs)} configs to evaluate") |
| print() |
|
|
| results = {} |
|
|
| for config_dir in configs: |
| config_name = config_dir.name |
| checkpoint = config_dir / "best.pt" |
| eval_out = config_dir / "lattice_eval.json" |
|
|
| print(f"Evaluating: {config_name}") |
|
|
| if not checkpoint.exists(): |
| print(f" ⚠️ Checkpoint not found: {checkpoint}") |
| results[config_name] = {"status": "missing_checkpoint"} |
| continue |
|
|
| |
| cmd = [ |
| sys.executable, "scripts/eval_lattice_checkpoint.py", |
| "--checkpoint", str(checkpoint), |
| "--dataset", str(args.dataset), |
| "--out", str(eval_out), |
| "--all-groups", |
| "--device", "cpu" |
| ] |
|
|
| try: |
| subprocess.run(cmd, check=True, capture_output=True, timeout=600) |
| print(f" ✓ Evaluation complete") |
|
|
| if eval_out.exists(): |
| with open(eval_out) as f: |
| data = json.load(f) |
| |
| results[config_name] = { |
| "status": "complete", |
| "selected_success_rate": data.get("selected_success_rate", |
| data.get("policy_rollout_success_rate", 0)), |
| "top1_action_selection": data.get("top1_action_selection", 0), |
| "pairwise_ranking_accuracy": data.get("pairwise_ranking_accuracy", 0), |
| "selection_regret": data.get("selection_regret", 0), |
| "oracle_success_rate": data.get("oracle_success_rate", 0) |
| } |
| print(f" Success: {results[config_name]['selected_success_rate']:.4f}") |
| else: |
| results[config_name] = {"status": "no_output"} |
|
|
| except subprocess.CalledProcessError as e: |
| print(f" ✗ Evaluation failed: {e}") |
| results[config_name] = {"status": "failed", "error": str(e)} |
| except subprocess.TimeoutExpired: |
| print(f" ⏰ Timeout") |
| results[config_name] = {"status": "timeout"} |
|
|
| print() |
|
|
| |
| print("=" * 70) |
| print("SUMMARY") |
| print("=" * 70) |
| print() |
|
|
| successful = [r for r in results.values() if r.get("status") == "complete"] |
| if successful: |
| |
| sorted_results = sorted(successful, |
| key=lambda x: x["selected_success_rate"], |
| reverse=True) |
|
|
| print("Top configurations:") |
| for i, r in enumerate(sorted_results[:5], 1): |
| print(f" {i}. {r['selected_success_rate']:.4f} (top1: {r['top1_action_selection']:.4f})") |
|
|
| best = sorted_results[0] |
| print() |
| print(f"Best config: {best['selected_success_rate']:.4f}") |
| print(f"Target 40%: {'✅ ACHIEVED' if best['selected_success_rate'] >= 0.40 else '❌ NOT YET'}") |
|
|
| |
| args.out.parent.mkdir(parents=True, exist_ok=True) |
| with open(args.out, "w") as f: |
| json.dump({ |
| "configs": results, |
| "best_by_success": max(successful, key=lambda x: x["selected_success_rate"]) if successful else None |
| }, f, indent=2) |
|
|
| print() |
| print(f"✅ Results saved to: {args.out}") |
|
|
| return 0 |
|
|
| if __name__ == "__main__": |
| sys.exit(main()) |
|
|