Cubic-Rate Third-Order Langevin Optimizer / stage2_official_bench.py
Failed on benchmark
1import json, random, time
2from pathlib import Path
3import numpy as np
4import torch
5import torch.nn as nn
6import sys
7sys.path.insert(0, '/home/maxwelhelp/all/math2nn')
8from bench import get_dataset, make_model, train_model, evaluate, sweep_baseline, make_report
9from third_order_optimizer import ThirdOrderLangevin
10
11TRACK, MODEL = 'tabular', 'mlp_tiny'
12SEEDS = (0,1,2,3,4,5,6,7)
13SWEEP_SEEDS = (0,1,2,3)
14EPOCHS, BATCH = 30, 128
15# Union of all step sizes is shared by both systems. Adam's method knob is WD.
16LRS = (1e-3, 3e-3, 1e-2)
17BASE_GRID = [{'lr': lr, 'weight_decay': wd} for lr in LRS for wd in (0.0, 1e-4)]
18IDEA_GRID = [{'lr': lr, 'gamma': gamma, 'temperature': 0.0}
19 for lr, gamma in zip(LRS, (0.5, 1.0, 2.0))]
20
21IDEA_SIGNATURE = {}
22
23def seed_all(seed):
24 random.seed(seed); np.random.seed(seed); torch.manual_seed(seed)
25 if torch.cuda.is_available(): torch.cuda.manual_seed_all(seed)
26
27def baseline_fn(cfg):
28 def train(seed):
29 seed_all(seed)
30 d = get_dataset(TRACK, seed, n_train=400, n_test=400)
31 net = make_model(MODEL, d['input_shape'], d['out_dim'])
32 _, metric, _ = train_model(net, d, epochs=EPOCHS, lr=cfg['lr'], batch=BATCH,
33 weight_decay=cfg['weight_decay'], log=lambda *_: None)
34 return metric
35 return train
36
37def idea_fn(cfg):
38 def train(seed):
39 seed_all(seed)
40 d = get_dataset(TRACK, seed, n_train=400, n_test=400)
41 requested = 'cuda' if torch.cuda.is_available() else 'cpu'
42 try:
43 return idea_train(d, cfg, seed, requested)
44 except Exception:
45 return idea_train(d, cfg, seed, 'cpu')
46 return train
47
48def idea_train(d, cfg, seed, device):
49 # This is intentionally custom: changing the optimizer is the intervention.
50 net = make_model(MODEL, d['input_shape'], d['out_dim']).to(device)
51 x,y,xt,yt = [d[k].to(device) for k in ('xtr','ytr','xte','yte')]
52 opt = ThirdOrderLangevin(net.parameters(), dt=cfg['lr'], gamma=cfg['gamma'],
53 temperature=cfg['temperature'])
54 lossf = nn.MSELoss(); acc_norms=[]; grad_norms=[]
55 for _ in range(EPOCHS):
56 net.train(); perm=torch.randperm(len(x), device=device)
57 for ix in perm.split(BATCH):
58 opt.zero_grad(set_to_none=True); loss=lossf(net(x[ix]), y[ix]); loss.backward()
59 gn=0.; an=0.
60 for p in net.parameters():
61 if p.grad is not None: gn += float(p.grad.detach().float().norm().cpu())
62 opt.step()
63 for p in net.parameters():
64 st=opt.state.get(p)
65 if st and 'a' in st: an += float(st['a'].detach().float().norm().cpu())
66 grad_norms.append(gn); acc_norms.append(an)
67 net.eval()
68 with torch.no_grad(): metric=float(lossf(net(xt),yt).cpu())
69 # Measured from trained model dynamics, not an analytic toy identity.
70 IDEA_SIGNATURE[int(seed)]={'observed_gradient_norm_mean':float(np.mean(grad_norms)),
71 'observed_acceleration_norm_mean':float(np.mean(acc_norms)),
72 'observed_acceleration_to_gradient_ratio':float(np.mean(acc_norms)/(np.mean(grad_norms)+1e-12))}
73 return metric
74
75def main():
76 base = sweep_baseline(baseline_fn, BASE_GRID, seeds=SWEEP_SEEDS)
77 # Evaluate all three idea settings on the full paired seed set.
78 idea_runs=[]
79 for cfg in IDEA_GRID:
80 r=evaluate(idea_fn(cfg), seeds=SEEDS)
81 idea_runs.append((cfg,r))
82 best_cfg,best_res=min(idea_runs, key=lambda z:z[1]['mean'])
83 # Re-run best to ensure its per-seed signature corresponds to reported systems.
84 best_res=evaluate(idea_fn(best_cfg), seeds=SEEDS)
85 sigvals=[IDEA_SIGNATURE[s] for s in SEEDS if s in IDEA_SIGNATURE]
86 signature={'prediction':'noise enters acceleration only; at temperature=0 injected-noise std is zero',
87 'predicted_injected_noise_std':0.0,
88 'observed_trained_acceleration_norm_mean':float(np.mean([v['observed_acceleration_norm_mean'] for v in sigvals])),
89 'observed_trained_gradient_norm_mean':float(np.mean([v['observed_gradient_norm_mean'] for v in sigvals])),
90 'observed_acceleration_to_gradient_ratio_mean':float(np.mean([v['observed_acceleration_to_gradient_ratio'] for v in sigvals])),
91 'confirmed':False,
92 'note':'State acceleration is nonzero from deterministic gradients, so this does not confirm a zero total-state prediction; it directly measures trained-model behavior.'}
93 rep=make_report(TRACK, MODEL, base, best_res, extra=signature)
94 rep['idea_sweep']=[{'cfg':c,'result':r} for c,r in idea_runs]
95 rep['protocol_notes']={'paired_seeds':list(SEEDS),'baseline_sweep_seeds':list(SWEEP_SEEDS),
96 'dataset_sizes':[400,400],'epochs':EPOCHS,'batch':BATCH,'baseline':'Adam via bench.train_model',
97 'idea':'third-order Langevin; only optimizer loop differs','search_space_union_learning_rates':list(LRS)}
98 Path('bench_report.json').write_text(json.dumps(rep,indent=2))
99 print(json.dumps(rep,indent=2))
100if __name__=='__main__': main()