fix: results.py parses gt_s/hack_s by header name, not stale fixed indices

Old GT_S=6/HACK_S=8 were the pre-sprd/N layout; current table is gt_s=4
hack_s=6, so newer logs were silently mis-read and old distill logs crashed
_frac on a non-fraction token. Now locate the train.py streaming header
(first token 'step' + 'ref_eq' present) and map columns by name.

Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
wassname
2026-05-31 22:45:12 +00:00
co-authored by Claudypoo
parent 47abce4307
commit ad048e59c6
+25 -4
View File
@@ -20,8 +20,14 @@ from tabulate import tabulate
LOG_DIR = Path("logs")
TS_RE = re.compile(r"(\d{8}T\d{6})")
# per-step row after "| INFO |": step ref_eq rew rew_s sprd N gt_s gt_t hack_s hack_t ...
GT_S, HACK_S = 6, 8 # column indices into the whitespace-split row
# Column positions are read from the header row by NAME, not hardcoded -- the
# per-step table layout has changed over time (sprd/N dropped, cin/cout/hk_dep
# added) so fixed indices silently mis-read newer logs and crash on smoke logs.
def _colname(tok: str) -> str:
# header tokens carry direction glyphs / markers: "gt_s↑", "hack_s?" -> "gt_s", "hack_s"
return re.sub(r"[^a-z0-9_]", "", tok.lower())
def _frac(tok: str) -> float | None:
@@ -64,14 +70,29 @@ def parse_log(path: Path) -> dict | None:
preset_line = next((l for l in txt.splitlines() if "preset=" in l and "arm=" in l), "")
if argv is None:
return None
# Locate the per-step table header to map gt_s/hack_s columns by NAME. The
# train.py streaming table is the INFO line whose tokens start with "step"
# and include "ref_eq" -- that signature excludes the old distill_* logs
# which also have "step ..." lines but a different (hack=.. pass=..) format.
header, names = None, []
for l in txt.splitlines():
if "| INFO |" not in l:
continue
toks = [_colname(t) for t in l.split("| INFO |", 1)[1].split()]
if toks[:1] == ["step"] and "ref_eq" in toks:
header, names = l, toks
break
if header is None:
return None # not a train.py streaming run
idx_hack, idx_gt = names.index("hack_s"), names.index("gt_s")
hs, gts = [], []
for line in txt.splitlines():
if "| INFO |" not in line:
continue
row = line.split("| INFO |", 1)[1].split()
if not row or not row[0].isdigit() or len(row) <= HACK_S:
if not row or not row[0].isdigit() or len(row) <= idx_hack:
continue
h, g = _frac(row[HACK_S]), _frac(row[GT_S])
h, g = _frac(row[idx_hack]), _frac(row[idx_gt])
if h is not None:
hs.append(h)
if g is not None: