summaryrefslogtreecommitdiff
path: root/ep_run
diff options
context:
space:
mode:
authorYuren Hao <yurenh2@illinois.edu>2026-07-17 08:33:55 -0500
committerYuren Hao <yurenh2@illinois.edu>2026-07-17 08:33:55 -0500
commit0ceeeb95316e170e1bbb8bfdbe7e8695da651273 (patch)
tree7904d90f8e7708a3d7b65c7f3f437469ed559c0d /ep_run
parent0cdd92cc4faece4b22dbf6123377904b2301128e (diff)
ride-v2: (a) floor-jump cap continuity (the 0.09 bug), (b) rho-EMA decisions, (c) 200-step post-attack cooldown, (d) adaptive drift ceiling (--drift_adapt); smoke: continuous beta across floor jump
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_eq_train.py28
1 files changed, 25 insertions, 3 deletions
diff --git a/ep_run/casc_eq_train.py b/ep_run/casc_eq_train.py
index fef44f0..8e3ec67 100644
--- a/ep_run/casc_eq_train.py
+++ b/ep_run/casc_eq_train.py
@@ -54,6 +54,9 @@ ap.add_argument('--ddp_grad_test', action='store_true') # one-step grad equival
ap.add_argument('--beta_ride', type=float, default=1.0) # cap ceiling: >1 lets the governor RAISE beta
# above the schedule, up to ride x schedule
ap.add_argument('--beta_ride_up', type=float, default=1.02) # per-step climb rate in the calm branch
+ap.add_argument('--drift_adapt', type=float, default=0.0) # >0: adaptive drift ceiling = this x trailing
+ # accepted-drift EMA (floor 0.05, cap 0.5);
+ # blocks beta-scaled garbage accepts (ride-v2d)
ap.add_argument('--beta_cap_rho', type=float, default=0.0) # >0: LOOP-GAIN CAP on beta — if per-sweep residual
# ratio rho^ exceeds this, bscale *= 0.8 (beta backs off
# under the wall-2 ceiling); recovers x1.02 when rho^ low
@@ -429,6 +432,13 @@ def ep_step(x, y):
fl = args.beta_floor
if args.bf_late > 0.0 and GOV.get('step', 0) >= args.bf_late_at: fl = args.bf_late
if fl > 0.0: beta_t = max(beta_t, fl)
+ if args.beta_ride > 1.0:
+ # ride-v2(a): floor jumps must not compose with a pre-charged cap — rescale cap so the
+ # EFFECTIVE beta is continuous across any floor change (the 0.09-at-20k bug, RESULT 37)
+ pf = GOV.get('prev_floor')
+ if pf is not None and fl != pf and pf > 0 and fl > 0:
+ GOV['cap'] = min(max(GOV.get('cap', 1.0) * pf / fl, 0.05), args.beta_ride)
+ GOV['prev_floor'] = fl
beta_t = beta_t * GOV.get('cap', 1.0) # wall-2 loop-gain cap OVERRIDES the floor (the ceiling
# can sit below the floor near the wall; survival first)
if args.bsign_rand and torch.rand((), generator=BGEN).item() < 0.5: beta_t = -beta_t
@@ -455,7 +465,14 @@ def ep_step(x, y):
with torch.no_grad():
drift = _drift(zp, zs_free)
gdrift = ddp_max_scalar(drift) # guard DECISIONS on the global worst -> identical on every rank
- if (not math.isfinite(gdrift)) or (gdrift > 0.5 and not args.noguard):
+ dthr = 0.5
+ if args.drift_adapt > 0:
+ # ride-v2(d): scale-free adaptive ceiling — reject anything far above the trailing
+ # ACCEPTED drift level (garbage is O(1); healthy drift scales with beta)
+ de = GOV.get('drift_ema')
+ if de is not None:
+ dthr = min(0.5, max(0.05, args.drift_adapt * de))
+ if (not math.isfinite(gdrift)) or (gdrift > dthr and not args.noguard):
ok_retry = False
if args.kretry > 0 and math.isfinite(gdrift) and not args.noguard:
GOV['skr'] = GOV.get('skr', 0) + 1 # marginal batch: retry once with deeper relaxation
@@ -471,14 +488,19 @@ def ep_step(x, y):
for p in all_params: p.grad = None
return free_ce, beta_t, GOV.get('kuse', GOV['K']), False
GOV['drift'] = gdrift
+ if args.drift_adapt > 0:
+ GOV['drift_ema'] = 0.95 * GOV.get('drift_ema', gdrift) + 0.05 * 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)
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:
+ rho_e = GOV['rho_ema'] = 0.9 * GOV.get('rho_ema', rho_g) + 0.1 * rho_g # ride-v2(b): smooth the meter
+ GOV['cool'] = max(GOV.get('cool', 0) - 1, 0)
+ if res_g > 0.02 and rho_e > 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['cool'] = 200 # ride-v2(c): no re-climb for 200 steps
+ elif (res_g < 0.01 or rho_e < 0.5 * args.beta_cap_rho) and GOV['cool'] == 0:
# recover; with beta_ride > 1 the governor CLIMBS past the schedule — beta finds
# its own ceiling and hovers there (ride-the-ceiling; 1.0 = legacy defensive cap)
GOV['cap'] = min(GOV.get('cap', 1.0) * args.beta_ride_up, args.beta_ride)