fsi-anomaly / research /eval_summary.py
FerrellSyntheticIntelligence's picture
backup all: 100 files (batch)
8b8e59d verified
Raw
History Blame Contribute Delete
2.44 kB
"""Recompute the honest battery scorecard from a per-battery eval log.
Scores are taken from the persisted per-probe lines so a device kill that
restarts eval.py mid-battery never loses or re-aggregates completed probes.
Exact-match on eval_labels.CANON, same protocol as research/eval.py.
Usage:
.venv/bin/python research/eval_summary.py logs/eval_cand_sft_best_main.log
"""
import argparse
import re
from pathlib import Path
from research import eval_labels as EL
LINE = re.compile(r"^\[(\S+)\] ([\d.]+|qual) \| verdict: (.+?) \| conf: (\S+)$")
def scored_ids(log_path):
"""Probe ids already scored in ANY section of a battery log (for resume)."""
ids = set()
if not Path(log_path).exists():
return ids
for ln in Path(log_path).read_text().splitlines():
m = LINE.match(ln.strip())
if m:
ids.add(m.group(1))
return ids
def cat_of(pid):
if pid.startswith("p") or pid.startswith("rt"):
return "generic"
return pid.rsplit("-", 1)[0]
def summarize(log_path):
scores, quals, formats = [], 0, 0
cat_acc = {}
seen = set()
for ln in Path(log_path).read_text().splitlines():
m = LINE.match(ln.strip())
if not m:
continue
pid, raw_sc, verdict, conf = m.groups()
if pid in seen:
continue # dedupe across resume sections; first occurrence wins
seen.add(pid)
canon = EL.CANON.get(pid)
ok_format = bool(verdict) and bool(conf)
formats += int(ok_format)
if canon is None:
quals += 1
else:
sc = 1.0 if verdict.strip().lower() == canon else 0.0
scores.append(sc)
cat_acc.setdefault(cat_of(pid), []).append(sc)
n = len(scores)
acc = sum(scores) / n if n else float("nan")
total = n + quals
fmt = formats / total if total else float("nan")
print(f"canonical verdict accuracy (exact): {acc:.3f} "
f"(n={n}, qualitative={quals}) format rate: {fmt:.2f}")
for cat, v in sorted(cat_acc.items()):
print(f" {cat:12s} acc {sum(v)/len(v):.3f} n={len(v)}")
return {"accuracy": acc, "n": n, "qualitative": quals,
"format_rate": fmt,
"by_category": {k: sum(v) / len(v) for k, v in cat_acc.items()}}
if __name__ == "__main__":
ap = argparse.ArgumentParser()
ap.add_argument("log")
args = ap.parse_args()
summarize(args.log)