| """Seed 17·31·47 P boundary joint 결과를 동일 gate로 집계한다.""" |
|
|
| from __future__ import annotations |
|
|
| import argparse |
| from datetime import datetime, timezone |
| import json |
| from pathlib import Path |
|
|
| import numpy as np |
|
|
| PROJECT_ROOT = Path(__file__).parents[1] |
|
|
|
|
| def _parse_args() -> argparse.Namespace: |
| """필요 변수: seed별 report·출력 경로. 작동 원리: 고정 3-seed 집계 CLI를 만든다.""" |
|
|
| parser = argparse.ArgumentParser(description="Summarize Math Ink 0.6 P boundary joint seeds") |
| parser.add_argument( |
| "--report", type=Path, action="append", default=None, |
| help="반복 지정한다. 생략하면 최초 legacy 3-seed report를 사용한다.", |
| ) |
| parser.add_argument("--output", type=Path, required=True) |
| return parser.parse_args() |
|
|
|
|
| def _summary06(values: list[float]) -> dict[str, float | list[float]]: |
| """필요 변수: seed별 실수 지표. 작동 원리: 원값·평균·표준편차·최저값을 함께 반환한다.""" |
|
|
| array = np.asarray(values, dtype=np.float64) |
| return { |
| "values": values, |
| "mean": float(array.mean()), |
| "std": float(array.std()), |
| "minimum": float(array.min()), |
| } |
|
|
|
|
| def main() -> None: |
| """필요 변수: seed 17·31·47 report. 작동 원리: 전 seed gate와 exact/family/boundary 개선을 요약한다.""" |
|
|
| args = _parse_args() |
| report_paths = args.report or [ |
| PROJECT_ROOT / "research/runs/math_ink_06_p_boundary_joint_seed17_20260724/report.json", |
| PROJECT_ROOT / "research/runs/math_ink_06_p_boundary_joint_seed31_20260724/report.json", |
| PROJECT_ROOT / "research/runs/math_ink_06_p_boundary_joint_seed47_20260724/report.json", |
| ] |
| reports = [json.loads(path.read_text(encoding="utf-8")) for path in report_paths] |
| seeds = [int(report["seed"]) for report in reports] |
| if sorted(seeds) != [17, 31, 47] or len(set(seeds)) != 3: |
| raise ValueError(f"필수 seed 17·31·47 report가 아닙니다: {seeds}") |
| metrics = { |
| "baseline_exact_top1": _summary06([ |
| float(report["baseline_test"]["exact_top1"]) for report in reports |
| ]), |
| "baseline_family_top1": _summary06([ |
| float(report["baseline_test"]["family_top1"]) for report in reports |
| ]), |
| "exact_top1": _summary06([ |
| float(report["official_test"]["authentic"]["exact_top1"]) for report in reports |
| ]), |
| "family_top1": _summary06([ |
| float(report["official_test"]["authentic"]["family_top1"]) for report in reports |
| ]), |
| "exact_gain_pp": _summary06([ |
| float(report["official_test"]["deltas"]["exact_top1_pp"]) for report in reports |
| ]), |
| "family_gain_pp": _summary06([ |
| float(report["official_test"]["deltas"]["family_top1_pp"]) for report in reports |
| ]), |
| "single_symbol_recall": _summary06([ |
| float(report["official_test"]["boundary"]["single_symbol_recall"]) for report in reports |
| ]), |
| "cross_boundary_recall": _summary06([ |
| float(report["official_test"]["boundary"]["cross_boundary_recall"]) for report in reports |
| ]), |
| "boundary_f1": _summary06([ |
| float(report["official_test"]["boundary"]["f1"]) for report in reports |
| ]), |
| } |
| all_seed_gate = all(bool(report["decision"]["release_adopted"]) for report in reports) |
| release_adopted = bool( |
| all_seed_gate |
| and metrics["exact_gain_pp"]["minimum"] > 0.0 |
| and metrics["family_gain_pp"]["minimum"] > 0.0 |
| and metrics["single_symbol_recall"]["minimum"] >= 0.95 |
| and metrics["cross_boundary_recall"]["minimum"] >= 0.95 |
| ) |
| summary = { |
| "experiment": "P-MATH-INK-06-BOUNDARY-JOINT-3SEED-001", |
| "generated_at": datetime.now(timezone.utc).isoformat(), |
| "seeds": seeds, |
| "reports": [str(path) for path in report_paths], |
| "metrics": metrics, |
| "decision": { |
| "all_seed_gate_passed": all_seed_gate, |
| "p_proxy_release_adopted": release_adopted, |
| "product_validation": False, |
| "next_gate": "실제 P 연속 수식 writer/device-disjoint boundary 평가", |
| }, |
| "track": "P_with_obligations", |
| "product_validation": False, |
| } |
| args.output.parent.mkdir(parents=True, exist_ok=True) |
| args.output.write_text( |
| json.dumps(summary, ensure_ascii=False, indent=2) + "\n", encoding="utf-8", |
| ) |
| print(json.dumps(summary, ensure_ascii=False, indent=2)) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|