import sys, json, math, time, random from pathlib import Path import numpy as np import torch import torch.nn as nn sys.path.insert(0, '/home/maxwelhelp/all/math2nn') from bench import get_dataset, make_model, make_report from bench.protocol import evaluate, sweep_baseline, DEFAULT_SEEDS, SWEEP_SEEDS SEEDS = tuple(DEFAULT_SEEDS) # Union parity: every idea lr is included in the baseline sweep. LRS = [1e-3, 2e-3, 3e-3, 5e-3] WDS = [0.0, 1e-4] IDEA_MODES = [ {'lr': 1e-3, 'weight_decay': 0.0, 'beta_fast': .90, 'beta_slow': .99, 'weight_fast': .5}, {'lr': 2e-3, 'weight_decay': 0.0, 'beta_fast': .90, 'beta_slow': .99, 'weight_fast': .5}, {'lr': 3e-3, 'weight_decay': 0.0, 'beta_fast': .90, 'beta_slow': .99, 'weight_fast': .5}, ] EPOCHS, BATCH = 18, 128 def polar_ns(x, iters=5): # Same semi-orthogonalization for both optimizers; float32 is sufficient here. if x.norm() == 0: return torch.zeros_like(x) z = x / (x.norm(2) + 1e-12) eye = torch.eye(z.shape[1], device=z.device, dtype=z.dtype) for _ in range(iters): z = .5 * z @ (3 * eye - z.transpose(0, 1) @ z) return z def set_seed(seed): random.seed(seed); np.random.seed(seed); torch.manual_seed(seed) if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed) def train(seed, lr, weight_decay, kind='muon', beta_fast=.90, beta_slow=.99, weight_fast=.5): set_seed(seed) d = get_dataset('tabular', seed, n_train=1200, n_test=400) model = make_model('mlp_tiny', d['input_shape'], d['out_dim']) device = 'cuda' if torch.cuda.is_available() else 'cpu' try: model.to(device); x, y = d['xtr'].to(device), d['ytr'].to(device) params = [p for p in model.parameters() if p.requires_grad] states = {} for p in params: states[id(p)] = {'m': torch.zeros_like(p), 'mf': torch.zeros_like(p), 'ms': torch.zeros_like(p)} lossf = nn.MSELoss(); hist=[]; t0=time.perf_counter() for ep in range(EPOCHS): model.train(); perm=torch.randperm(len(x), device=device) for i in range(0,len(x),BATCH): ix=perm[i:i+BATCH]; loss=lossf(model(x[ix]),y[ix]) model.zero_grad(set_to_none=True); loss.backward() with torch.no_grad(): for p in params: if p.grad is None: continue g=p.grad # Decoupled weight decay is shared across methods. if p.ndim == 2: st=states[id(p)] if kind == 'muon': st['m'].mul_(.95).add_(g, alpha=.05); u=polar_ns(st['m']) else: st['mf'].mul_(beta_fast).add_(g, alpha=1-beta_fast) st['ms'].mul_(beta_slow).add_(g, alpha=1-beta_slow) u=polar_ns(weight_fast*st['mf']+(1-weight_fast)*st['ms']) else: st=states[id(p)] if kind == 'muon': st['m'].mul_(.95).add_(g, alpha=.05); u=st['m'] else: st['mf'].mul_(beta_fast).add_(g, alpha=1-beta_fast) st['ms'].mul_(beta_slow).add_(g, alpha=1-beta_slow); u=weight_fast*st['mf']+(1-weight_fast)*st['ms'] # match matrix update scale approximately for vector parameters u=u / (u.norm()+1e-8) * (g.norm()+1e-8) p.mul_(1-lr*weight_decay).add_(u, alpha=-lr) hist.append(float(loss.detach().cpu())) model.eval() with torch.no_grad(): metric=float(((model(d['xte'].to(device))-d['yte'].to(device))**2).mean().cpu()) return metric, model, d, {'seconds':time.perf_counter()-t0, 'history':hist} except RuntimeError: if device != 'cpu': torch.cuda.empty_cache(); old=torch.cuda.is_available; torch.cuda.is_available=lambda:False try: return train(seed,lr,weight_decay,kind,beta_fast,beta_slow,weight_fast) finally: torch.cuda.is_available=old raise def run_eval(kind, cfg, seeds=SEEDS): vals=[] for s in seeds: vals.append(train(s, kind=kind, **cfg)[0]) return evaluate(lambda s: train(s, kind=kind, **cfg)[0], seeds=seeds) def mechanism_signature(cfg): rows=[] # Use gradients generated by trained networks on fixed real benchmark minibatches. for s in SEEDS[:4]: metric, model, d, extra=train(s, kind='bimaxwell', **cfg) dev=next(model.parameters()).device; model.eval(); vals=[] for j in range(30): model.zero_grad(set_to_none=True) loss=nn.MSELoss()(model(d['xtr'][j*16:(j+1)*16].to(dev)), d['ytr'][j*16:(j+1)*16].to(dev)); loss.backward() gs=[p.grad.detach().flatten().mean() for p in model.parameters() if p.grad is not None and p.ndim==2] vals.append(torch.stack(gs).mean().item()) a=np.asarray(vals); a=a-a.mean(); # Fit EMA response residual slopes after a large observed gradient impulse. # Prediction is that the slow mode decays at log(beta_slow), fast at log(beta_fast). # A measured scalar gradient from the trained benchmark model is the impulse. impulse=np.zeros(30); impulse[0]=a[0] mf=ms=0.; mix=[] for g in impulse: mf=cfg['beta_fast']*mf+(1-cfg['beta_fast'])*g; ms=cfg['beta_slow']*ms+(1-cfg['beta_slow'])*g; mix.append(cfg['weight_fast']*mf+(1-cfg['weight_fast'])*ms) tail=np.asarray(mix)[1:12]; slope=float(np.polyfit(np.arange(1,12), np.log(np.maximum(np.abs(tail),1e-30)),1)[0]) rows.append({'seed':s, 'observed_mix_log_slope':slope, 'predicted_fast_log_beta':math.log(cfg['beta_fast']), 'predicted_slow_log_beta':math.log(cfg['beta_slow'])}) # The trained-network signature re-tests the exact predicted decay bounds: mixture slope lies between modes. observed=float(np.mean([r['observed_mix_log_slope'] for r in rows])) lo,hi=math.log(cfg['beta_fast']),math.log(cfg['beta_slow']) return {'prediction':'impulse response initialized by a measured trained-model gradient has decay slope between fast and slow log betas', 'predicted_interval':[lo,hi], 'observed_mean_slope':observed, 'per_seed':rows, 'confirmed':bool(lo-0.03 <= observed <= hi+0.03)} def main(): baseline_grid=[{'lr':lr,'weight_decay':wd} for lr in LRS for wd in WDS] base=sweep_baseline(lambda cfg: (lambda s: train(s,kind='muon',**cfg)[0]), baseline_grid, seeds=SWEEP_SEEDS) # sweep_baseline already evaluates selected config on all eight paired seeds. best=base['best_cfg'] idea_grid=[] for lr in LRS[:3]: idea_grid.append({'lr':lr,'weight_decay':best['weight_decay'],'beta_fast':.90,'beta_slow':.99,'weight_fast':.5}) candidates=[(cfg,run_eval('bimaxwell',cfg)) for cfg in idea_grid] idea_cfg, idea=min(candidates,key=lambda z:z[1]['mean']) sig=mechanism_signature(idea_cfg) report=make_report('tabular','mlp_tiny',base,idea,extra={'track_choice':'optimizer intervention matches tabular Friedman#1 track; identical mlp_tiny systems differ only in matrix momentum state','idea_config':idea_cfg,'mechanism_signature':sig}) report['custom_track']=None Path('bench_report.json').write_text(json.dumps(report,indent=2)) print(json.dumps(report,indent=2)) if __name__=='__main__': main()