summaryrefslogtreecommitdiff
path: root/ep_run
diff options
context:
space:
mode:
authorYuren Hao <yurenh2@illinois.edu>2026-07-22 18:38:06 -0500
committerYuren Hao <yurenh2@illinois.edu>2026-07-22 18:38:06 -0500
commit36690bb0abf236ed0f508c22b54732302cafc8ff (patch)
tree8f0b108d0d62f42c36b2e95273c6e611ab24f723 /ep_run
parente903c185c471d7149650e3b337669d7b6355e564 (diff)
遥测扩展(用户规格): wandb新键 gn/clip_norm/clip_fired + watch_every(2k)act_rms/w_rms + gate处mag_ep/mag_bp — 打印行格式冻结(sync正则兼容),BP孪生镜像; 冒烟认证LOGCERT_PASS(8键API读回,gn=clip=mag_ep互证)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FAPDWQ49M5Ye3NpTndTpn
Diffstat (limited to 'ep_run')
-rw-r--r--ep_run/casc_bp_train.py9
-rw-r--r--ep_run/casc_eq_train.py16
2 files changed, 21 insertions, 4 deletions
diff --git a/ep_run/casc_bp_train.py b/ep_run/casc_bp_train.py
index 0515ec1..42acf16 100644
--- a/ep_run/casc_bp_train.py
+++ b/ep_run/casc_bp_train.py
@@ -13,6 +13,7 @@ ap.add_argument('--B', type=int, default=24); ap.add_argument('--steps', type=in
ap.add_argument('--lr', type=float, default=3e-4); ap.add_argument('--warmup', type=int, default=200)
ap.add_argument('--seed', type=int, default=0)
ap.add_argument('--save_every', type=int, default=500); ap.add_argument('--log', type=int, default=200)
+ap.add_argument('--watch_every', type=int, default=2000) # wandb-only telemetry: weight/act RMS
ap.add_argument('--wandb', default='auto') # ON BY DEFAULT; 'auto' = per-regime project (ept-fineweb-72m / ept-tinystories-42m); --wandb '' to disable
ap.add_argument('--wandb_run', default='')
ap.add_argument('--amp', action='store_true') # bf16 autocast fwd/loss (no scaler needed for bf16)
@@ -219,7 +220,7 @@ for step in range(start_step, args.steps + 1):
if args.qcomp_bits > 0:
with torch.no_grad():
for p, q in zip(params, QSAVE): p.copy_(q)
- torch.nn.utils.clip_grad_norm_(params, 1.0)
+ CLIP_NORM = float(torch.nn.utils.clip_grad_norm_(params, 1.0))
opt.step(); sched.step()
if args.qup_bits > 0:
with torch.no_grad():
@@ -236,7 +237,11 @@ for step in range(start_step, args.steps + 1):
print(f'step {step:5d}/{args.steps} | train {loss.item():.4f} val {val:.4f} (best {best:.4f}) '
f'| {step/max(time.time()-t0,1e-9):.2f} it/s', flush=True)
if wb is not None:
- try: wb.log({'train_ce': loss.item(), 'val_ce': val, 'best': best}, step=step)
+ _aux = {'clip_norm': CLIP_NORM, 'clip_fired': float(CLIP_NORM > 1.0), 'gn': CLIP_NORM}
+ if args.watch_every > 0 and step % args.watch_every == 0:
+ with torch.no_grad():
+ _aux['w_rms'] = float(sum(p.float().pow(2).mean().sqrt() for p in params) / len(params))
+ try: wb.log({'train_ce': loss.item(), 'val_ce': val, 'best': best, **_aux}, step=step)
except Exception: pass
if step % args.save_every == 0 or step == args.steps:
torch.save({'tok': tok.state_dict(), 'pos': pos.state_dict(), 'blocks': blocks.state_dict(),
diff --git a/ep_run/casc_eq_train.py b/ep_run/casc_eq_train.py
index 74aab93..eb64082 100644
--- a/ep_run/casc_eq_train.py
+++ b/ep_run/casc_eq_train.py
@@ -49,6 +49,7 @@ ap.add_argument('--bsign_rand', action='store_true') # random-sign beta per ste
ap.add_argument('--bf16', action='store_true') # cast model to bf16 (E-accumulation + tok_sigma stay fp32) — the x0.5 cost lever, GATE before production
ap.add_argument('--amp', action='store_true') # PROPER mixed precision: autocast(bf16) matmuls, fp32 params/states/d/E — amp_gate.py PASSED 2026-07-12 (cos 0.9682 vs fp32 0.9687); --bf16 naive-cast stays DEAD (state quantization, RESULT 11)
ap.add_argument('--dtop_every', type=int, default=1) # 1 = exact (DEFAULT, BP-parity); 2 = fast mode (~20% cheaper, ~4% CE tax at high lr)
+ap.add_argument('--watch_every', type=int, default=2000) # wandb-only telemetry cadence: act/weight RMS
ap.add_argument('--gate_every', type=int, default=200) # in-training cos(EP,BP) telemetry; <=0 = fully BP-free (no bp_gate at all)
ap.add_argument('--gate_govern', action='store_true') # let gate cos adjust K/bscale (default: observe-only => training control is BP-free)
ap.add_argument('--data', default='tinystories_bpe') # dataset dir under ep_run/data (train.bin/val.bin/meta.pkl)
@@ -514,6 +515,9 @@ def ep_step(x, y):
x_in, y_in, bmask, halves = x, y, None, (slice(None),)
z0, zs, ins, outs = free_states_graphed(x_in)
zs_free = [z.clone() for z in zs]
+ if args.watch_every > 0 and GOV['step'] % args.watch_every == 0:
+ with torch.no_grad():
+ GOV['act_rms'] = float(sum(z.float().pow(2).mean().sqrt() for z in zs_free) / len(zs_free))
free_ce = F.cross_entropy(readout(zs_free[-1][:args.B]).reshape(-1, vocab), y.reshape(-1)).item()
zp, last_outs = relax(z0, zs, ins, outs, y_in, +beta_t, GOV['K'], x_in, bmask=bmask)
def _drift(zp_, zf_):
@@ -833,6 +837,7 @@ for step in range(start_step, args.steps + 1):
if p.grad is None or g is None: continue
num += float((p.grad * g).sum()); den1 += float((p.grad ** 2).sum()); den2 += float((g ** 2).sum())
gcos = num / max((den1 ** 0.5) * (den2 ** 0.5), 1e-12)
+ GOV['mag_ep'], GOV['mag_bp'] = den1 ** 0.5, den2 ** 0.5
if args.gate_govern: # opt-in: BP-informed control flow
if gcos < 0.97:
GOV['K'] = min(GOV['K'] + 2, args.kmax); GOV['bscale'] = max(GOV['bscale'] * 0.7, 0.05)
@@ -857,7 +862,7 @@ for step in range(start_step, args.steps + 1):
for p, g in zip(all_params, _bg):
if id(p) in sel and g is not None:
p.grad = g.detach().clone()
- torch.nn.utils.clip_grad_norm_(all_params, 1.0)
+ GOV['clip_norm'] = float(torch.nn.utils.clip_grad_norm_(all_params, 1.0))
if args.wsync > 0:
# snapshot the KNOWN-LEGAL pre-step state (this step's relax passed _legal);
# next step's relax measures the post-step state and can roll back to here.
@@ -894,8 +899,15 @@ for step in range(start_step, args.steps + 1):
f'| beta={beta_t:.2e} K={rounds} skips={skips}(d{GOV.get("skd",0)}/g{GOV.get("skg",0)}/r{GOV.get("skr",0)}){gtag} '
f'drift={GOV["drift"]:.3f} gn={GOV["gn"]:.2e} sig={GOV["sig"]:.1f} | {step/max(time.time()-t0,1e-9):.3f} it/s', flush=True)
if wb is not None:
+ if args.watch_every > 0 and step % args.watch_every == 0:
+ with torch.no_grad():
+ GOV['w_rms'] = float(sum(p.float().pow(2).mean().sqrt() for p in all_params) / len(all_params))
+ _aux = {'gn': GOV.get('gn'), 'drift': GOV.get('drift'), 'sig': GOV.get('sig'),
+ 'clip_norm': GOV.get('clip_norm'), 'clip_fired': (None if GOV.get('clip_norm') is None else float(GOV['clip_norm'] > 1.0))}
+ for k in ('act_rms', 'w_rms', 'mag_ep', 'mag_bp'):
+ if GOV.get(k) is not None: _aux[k] = GOV[k]
try: wb.log({'train_ce': ce, 'val_ce': val, 'best': best, 'beta_t': beta_t,
- 'rounds': rounds, 'skips': skips, 'gate_cos': (None if math.isnan(gcos) else gcos)}, step=step)
+ 'rounds': rounds, 'skips': skips, 'gate_cos': (None if math.isnan(gcos) else gcos), **_aux}, step=step)
except Exception: pass
if (step % args.save_every == 0 or step == args.steps) and step > 0 and RANK == 0:
torch.save({'tok': tok.state_dict(), 'pos': pos.state_dict(), 'blocks': blocks.state_dict(),