summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuren Hao <yurenh2@illinois.edu>2026-07-14 11:38:44 -0500
committerYuren Hao <yurenh2@illinois.edu>2026-07-14 11:38:44 -0500
commitbba77d7a45ac29f5a640dac26c097752db1a59bb (patch)
tree528a48f8449f7938c2194e0976c800fbc0473e07
parent70e6ee77b28d447de01b489d8808893d1d9e82dc (diff)
bcap v2: absolute-scale gate on rho meter (fixes v1 noise-floor starvation), gentler attack 0.85/floor 0.05; crown c2 relaunched from s215000 with cap armed
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014FAPDWQ49M5Ye3NpTndTpn
-rw-r--r--ep_run/casc_eq_train.py12
1 files changed, 8 insertions, 4 deletions
diff --git a/ep_run/casc_eq_train.py b/ep_run/casc_eq_train.py
index 7b9780c..faf827e 100644
--- a/ep_run/casc_eq_train.py
+++ b/ep_run/casc_eq_train.py
@@ -351,6 +351,7 @@ def relax(z0, zs, ins, outs, y, beta, K, x):
rlist.append(rebuild(k + 1 == K))
if len(rlist) >= 2 and rlist[-2] > 1e-12:
GOV['rho'] = rlist[-1] / rlist[-2] # per-sweep contraction ratio = live loop-gain meter
+ GOV['res'] = rlist[-1]
GOV['kuse'] = K
return zs, outs
@@ -434,10 +435,13 @@ def ep_step(x, y):
GOV['drift'] = gdrift
if args.beta_cap_rho > 0 and GOV.get('rho') is not None:
rho_g = ddp_bcast_scalar(GOV['rho']) # rank0's meter rules (identical control on all ranks)
- if rho_g > args.beta_cap_rho:
- GOV['cap'] = max(GOV.get('cap', 1.0) * 0.8, 0.02) # back beta off under the wall-2 ceiling
- elif rho_g < 0.5 * args.beta_cap_rho:
- GOV['cap'] = min(GOV.get('cap', 1.0) * 1.02, 1.0) # slow recovery toward schedule
+ res_g = ddp_bcast_scalar(GOV.get('res', 0.0))
+ # v2: ABSOLUTE-SCALE GATE — rho is only meaningful when the residual is above the noise
+ # floor; at tiny residuals rho ~ noise/noise ~ 1 and v1 starved beta to the cap floor.
+ if res_g > 0.02 and rho_g > args.beta_cap_rho:
+ GOV['cap'] = max(GOV.get('cap', 1.0) * 0.85, 0.05) # attack (gentler than v1)
+ elif res_g < 0.01 or rho_g < 0.5 * args.beta_cap_rho:
+ GOV['cap'] = min(GOV.get('cap', 1.0) * 1.02, 1.0) # recover
E = 0.0
for z, o in zip(zp, last_outs): E = E + 0.5 * ((z.detach().float() - o.float()) ** 2).sum() # fp32 accumulation (bf16-safe; no-op in fp32)
if args.est == 'single':