Drop7 Research
approaches/lifetime-objective/leaf-capacity-sweep/summarize.pyPython48 lines · 3.0 KB
#!/usr/bin/env python3
"""Tabulate the sweep's held-out metrics and evaluate the preregistered gate.

Gate (EX-20260822-nnue-leaf-capacity-sweep): let base be the h64-m32-e10-lr3e-3
seed-0 run, spread the largest |Pearson(seed k) - Pearson(base)| over the
seed replicas, and delta the best non-replica configuration's Pearson minus
base.  supported-as-tested (saturated) if delta <= max(0.005, 2*spread);
not-supported (capacity/training matters) if delta >= 0.02 and delta > 3*spread;
inconclusive otherwise.  Nothing here is a gameplay claim.
"""
import json, sys, glob, os

run = sys.argv[1]
rows = []
for path in sorted(glob.glob(os.path.join(run, "models", "*.json"))):
    d = json.load(open(path))
    tag = os.path.basename(path)[:-5]
    ho = d["heldOut"]
    rows.append({
        "tag": tag, "hidden": d["args"]["hidden"], "mid": d["args"]["mid"], "epochs": d["args"]["epochs"],
        "lr": d["args"]["lr"], "seed": d["args"]["seed"], "parameters": d["parameters"],
        "lifetimePearson": ho["lifetimePearson"], "lifetimeMAE": ho["lifetimeMeanAbsoluteErrorMoves"],
        "hazardAccMean": sum(ho["hazardAccuracyByRise"]) / len(ho["hazardAccuracyByRise"]),
        "mirroredPearson": d["heldOutMirrored"]["lifetimePearson"],
        "trainWallSeconds": d["history"][-1]["wallSeconds"], "finalTrainLoss": d["history"][-1]["trainLoss"],
    })
by = {r["tag"]: r for r in rows}
base = by.get("h64-m32-e10-lr3e3-s0")
out = {"format": "drop7-leaf-capacity-sweep-summary-v1", "runs": rows}
if base:
    replicas = [by[t] for t in ("h64-m32-e10-lr3e3-s1", "h64-m32-e10-lr3e3-s2") if t in by]
    spread = max([abs(r["lifetimePearson"] - base["lifetimePearson"]) for r in replicas], default=None)
    others = [r for r in rows if not r["tag"].startswith("h64-m32-e10-lr3e3-s")]
    best = max(others, key=lambda r: r["lifetimePearson"]) if others else None
    delta = best["lifetimePearson"] - base["lifetimePearson"] if best else None
    verdict = None
    if spread is not None and delta is not None:
        if delta <= max(0.005, 2 * spread): verdict = "supported-as-tested"
        elif delta >= 0.02 and delta > 3 * spread: verdict = "not-supported-as-tested"
        else: verdict = "inconclusive"
    out.update({"basePearson": base["lifetimePearson"], "seedSpread": spread, "bestTag": best["tag"] if best else None,
                "bestPearson": best["lifetimePearson"] if best else None, "deltaBestMinusBase": delta, "gateVerdict": verdict})
json.dump(out, open(os.path.join(run, "summary.json"), "w"), indent=2)
print(f"{'tag':24} {'params':>9} {'pearson':>8} {'mirror':>8} {'MAE':>7} {'hazAcc':>7} {'loss':>7} {'wall':>6}")
for r in rows:
    print(f"{r['tag']:24} {r['parameters']:9d} {r['lifetimePearson']:8.4f} {r['mirroredPearson']:8.4f} {r['lifetimeMAE']:7.2f} {r['hazardAccMean']:7.4f} {r['finalTrainLoss']:7.4f} {r['trainWallSeconds']:6.0f}")
if base:
    print(f"base {out['basePearson']:.4f}  seed spread {out['seedSpread']}  best {out['bestTag']} {out['bestPearson']}  delta {out['deltaBestMinusBase']}  verdict {out['gateVerdict']}")