diff options
| author | Yuren Hao <yurenh2@illinois.edu> | 2026-07-22 18:38:06 -0500 |
|---|---|---|
| committer | Yuren Hao <yurenh2@illinois.edu> | 2026-07-22 18:38:06 -0500 |
| commit | 36690bb0abf236ed0f508c22b54732302cafc8ff (patch) | |
| tree | 8f0b108d0d62f42c36b2e95273c6e611ab24f723 /ep_run | |
| parent | e903c185c471d7149650e3b337669d7b6355e564 (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.py | 9 | ||||
| -rw-r--r-- | ep_run/casc_eq_train.py | 16 |
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(), |
