summaryrefslogtreecommitdiff
path: root/ep_run/backfill_wandb.py
blob: 37b04e3e8691e534baf694482a6825d284d58b0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
"""Backfill historical run logs into W&B (one wandb run per log, replayed at original steps).
Handles both trainer formats:
  ep:  step  100/32000 | val CE 2.99 ema=3.29 (best 2.99) | jr=0.1 res=8.7e-03 [rho=0.85] | 0.09 it/s
  bp:  step   200/32000 | val 3.4503 ema 7.9637 (best 3.4503) | 16.47 it/s
Governor / ABORT / DONE lines land in run.summary. Re-runnable: id = run name (resume overwrite).
Usage: python3 backfill_wandb.py            # backfill the curated map below
"""
import re, glob, os
import wandb

EP = re.compile(r'step\s+(\d+)/\d+ \| val CE ([\d.]+)(?: ema=([\d.]+))? \(best ([\d.]+)\) \| jr=([\d.]+) res=([\d.eE+-]+)(?: rho=([\d.]+))?.* ([\d.]+) it/s')
BP = re.compile(r'step\s+(\d+)/\d+ \| val ([\d.]+)(?: ema ([\d.]+))? \(best ([\d.]+)\).* ([\d.]+) it/s')

MAP = {  # glob -> (project, strip_suffixes)
    'runs/gov_s1[1-5].log':        'ept-c512',
    'runs/abl_*.log':              'ept-c512',
    'runs/ep_warm_fast.log':       'ept-c512',
    'runs/self_restart*.log':      'ept-c512',
    'runs/bp_lm.log':              'ept-c512',
    'runs/tol2_*.log':             'ept-tol',
    'runs/tol_*.log':              'ept-tol',
    'runs/par_*.log':              'ept-c512',
    'runs/delta_mirror/rung33m*.out': 'ept-33m',
}

def backfill(path, project):
    name = re.sub(r'_\d{6,}$', '', os.path.splitext(os.path.basename(path))[0])
    rows, events, done = [], [], None
    for ln in open(path, errors='replace'):
        m = EP.search(ln)
        if m:
            s, v, e, b, jr, res, rho, ips = m.groups()
            r = {'val_ce': float(v), 'best': float(b), 'jr': float(jr), 'res': float(res), 'it_per_s': float(ips)}
            if e: r['ema_ce'] = float(e)
            if rho: r['rho'] = float(rho)
            rows.append((int(s), r)); continue
        m = BP.search(ln)
        if m:
            s, v, e, b, ips = m.groups()
            r = {'val_ce': float(v), 'best': float(b), 'it_per_s': float(ips)}
            if e: r['ema_ce'] = float(e)
            rows.append((int(s), r)); continue
        if '[governor]' in ln or 'ABORT' in ln:
            events.append(ln.strip())
        if 'DONE best val CE' in ln:
            done = float(re.search(r'DONE best val CE ([\d.]+)', ln).group(1))
    if not rows:
        print(f'  skip (no rows): {path}'); return
    rows.sort(key=lambda t: t[0])
    last = -1
    run = wandb.init(project=project, name=name, id=name, resume='allow',
                     tags=['backfill'], config={'source_log': path}, reinit=True)
    for s, r in rows:
        if s <= last: continue   # resumed-run overlap: keep first pass, monotone steps only
        run.log(r, step=s); last = s
    bestv = done if done is not None else min(r['best'] for _, r in rows)
    run.summary['best_val_ce'] = bestv
    run.summary['final_step'] = last
    if events: run.summary['events'] = events[:40]
    if done is not None: run.summary['done'] = True
    run.finish()
    print(f'  {project}/{name}: {len(rows)} pts, best {bestv}, events {len(events)}')

seen = set()
for pat, project in MAP.items():
    for p in sorted(glob.glob(pat)):
        if p in seen: continue
        seen.add(p)
        try: backfill(p, project)
        except Exception as e: print(f'  ERROR {p}: {e}')
print(f'backfill complete: {len(seen)} logs')