Transient-risk certificate for Langevin training / official_bench.py

Mechanism confirmed, baseline not beaten

Raw ⬇ ZIP
 1import sys, json, math
 2from pathlib import Path
 3import numpy as np
 4import torch
 5
 6sys.path.insert(0, '/home/maxwelhelp/all/math2nn')
 7from bench import get_dataset, make_model, sweep_baseline, evaluate, make_report
 8
 9TRACK='tabular'; MODEL='mlp_tiny'; EPOCHS=18; BATCH=128
10# Union is shared: baseline is evaluated at every lr and temperature used by idea.
11GRID=[{'lr':lr,'temperature':t} for lr in (0.001,0.003,0.006) for t in (0.0005,0.002)]
12IDEA_GRID=GRID[:3]
13SEEDS=tuple(range(8))
14OBS={}
15
16def run(seed, cfg, controlled, record=False):
17    torch.manual_seed(seed); np.random.seed(seed)
18    ds=get_dataset(TRACK, seed, n_train=4000, n_test=1000)
19    net=make_model(MODEL, ds['input_shape'], ds['out_dim'])
20    # A fixed unsafe region in parameter space: leaving the initialization basin.
21    initial=[p.detach().clone() for p in net.parameters()]
22    threshold=1.5; m=0.15; chi2=4.0; delta=0.20
23    x,y=ds['xtr'],ds['ytr']; xt,yt=ds['xte'],ds['yte']
24    g=torch.Generator().manual_seed(seed+19001)
25    stopped=False; stop_epoch=None; unsafe=[]; bounds=[]; radii=[]
26    for ep in range(EPOCHS):
27        perm=torch.randperm(len(x), generator=g)
28        for j in range(0,len(x),BATCH):
29            idx=perm[j:j+BATCH]
30            loss=((net(x[idx])-y[idx])**2).mean()
31            net.zero_grad(set_to_none=True); loss.backward()
32            temp=0.0 if (controlled and stopped) else cfg['temperature']
33            with torch.no_grad():
34                for p in net.parameters():
35                    if p.grad is not None:
36                        p.add_(-cfg['lr']*p.grad)
37                        if temp>0:
38                            p.add_(math.sqrt(2*cfg['lr']*temp)*torch.randn(p.shape))
39        with torch.no_grad():
40            radius=float(torch.sqrt(sum(((p-a)**2).sum() for p,a in zip(net.parameters(),initial))))
41        # Empirical local Gaussian proxy for stationary event probability.
42        scale=max(float(torch.sqrt(sum((p**2).sum() for p in net.parameters())))/18.,1e-4)
43        z=(threshold-radius)/scale
44        pi=float(.5*math.erfc(max(min(z,8.),-8.)/math.sqrt(2)))
45        pi=min(max(pi,1e-3),1-1e-3)
46        bound=min(1.,pi+math.sqrt(pi*chi2)*math.exp(-m*(ep+1)))
47        radii.append(radius); bounds.append(bound); unsafe.append(float(radius>threshold))
48        if controlled and not stopped and bound<=delta:
49            stopped=True; stop_epoch=ep+1
50    net.eval()
51    with torch.no_grad(): metric=float(((net(xt)-yt)**2).mean())
52    result={'metric':metric,'mse':metric,'max_unsafe':max(unsafe),'mean_unsafe':float(np.mean(unsafe)),
53            'post_stop_unsafe':float(np.mean(unsafe[stop_epoch-1:])) if stop_epoch else float(np.mean(unsafe)),
54            'stop_epoch':stop_epoch,'final_radius':radii[-1],'final_bound':bounds[-1]}
55    if record: OBS.setdefault('records',[]).append(result)
56    return result if record else metric
57
58def baseline_fn(cfg):
59    return lambda seed: run(seed,cfg,False)
60def idea_fn(cfg):
61    def train(seed):
62        out=run(seed,cfg,True,True)
63        return out['metric']
64    return train
65
66def main():
67    base=sweep_baseline(baseline_fn, GRID)
68    # Three idea settings, all present in baseline union; choose by 4-seed pilot.
69    pilots=[]
70    for cfg in IDEA_GRID:
71        r=evaluate(lambda s: run(s,cfg,True), seeds=(0,1,2,3))
72        pilots.append((r['mean'],cfg))
73    best_cfg=min(pilots,key=lambda x:x[0])[1]
74    idea=evaluate(idea_fn(best_cfg))
75    # Signature is measured from trained idea systems and tests the transient claim.
76    rr=[r for r in OBS.get('records',[]) if 'final_bound' in r]
77    sig={'prediction':'observed unsafe frequency should not exceed certificate envelope',
78         'predicted_final_bound':float(np.mean([r['final_bound'] for r in rr])) if rr else None,
79         'observed_mean_unsafe_frequency':float(np.mean([r['mean_unsafe'] for r in rr])) if rr else None,
80         'observed_post_stop_unsafe_frequency':float(np.mean([r['post_stop_unsafe'] for r in rr])) if rr else None,
81         'n_trained_models':len(rr)}
82    sig['confirmed']=bool(sig['observed_mean_unsafe_frequency'] <= sig['predicted_final_bound']*1.25+0.02)
83    rep=make_report(TRACK,MODEL,base,idea,{'mechanism_signature':sig,
84        'idea_sweep':pilots,'protocol_note':'Official bench tabular track; custom Langevin loop is the intervention.'})
85    Path('bench_report.json').write_text(json.dumps(rep,indent=2))
86    print(json.dumps({'comparison':rep['comparison'],'baseline_best':base['best_cfg'],
87                      'idea_best':best_cfg,'signature':sig},indent=2))
88
89if __name__=='__main__': main()