Kac-Ward Exact Teacher for Autoregressive Samplers / stage2_bench.py

Mechanism confirmed, baseline not beaten

Raw ⬇ ZIP
 1import json, random, importlib.util, sys
 2from pathlib import Path
 3import numpy as np
 4import torch
 5import torch.nn as nn
 6sys.path.insert(0, '/home/maxwelhelp/all/math2nn')
 7from bench import make_model, sweep_baseline, evaluate, make_report, validate_and_promote, reload_custom_tracks
 8
 9TRACK='planar_ising_autoregressive'; SEEDS=tuple(range(8))
10GRID=[{'lr':lr,'epochs':5,'batch':128} for lr in (.001,.003,.01)]
11HERE=Path(__file__).resolve().parent
12spec=importlib.util.spec_from_file_location('local_ising_track', HERE/'ising_teacher_track.py')
13MOD=importlib.util.module_from_spec(spec); spec.loader.exec_module(MOD)
14
15def seed_all(s):
16    random.seed(s); np.random.seed(s); torch.manual_seed(s)
17    if torch.cuda.is_available(): torch.cuda.manual_seed_all(s)
18
19def train_one(seed,cfg,soft,capture=False):
20    seed_all(seed); raw=MOD.get_dataset(seed,400,200)
21    xtr=torch.tensor(raw['xtr']); ytr=torch.tensor(raw['ytr']); xte=torch.tensor(raw['xte'])
22    target=torch.tensor(raw['qtr'] if soft else raw['ytr'])
23    net=make_model('mlp_tiny',tuple(xtr.shape[1:]),1)
24    try:
25        dev='cuda' if torch.cuda.is_available() else 'cpu'; net.to(dev)
26        xtr,target=xtr.to(dev),target.to(dev); opt=torch.optim.Adam(net.parameters(),lr=cfg['lr'])
27        for _ in range(cfg['epochs']):
28            p=torch.randperm(len(xtr),device=dev)
29            for st in range(0,len(p),cfg['batch']):
30                ix=p[st:st+cfg['batch']]; loss=nn.functional.mse_loss(net(xtr[ix]),target[ix])
31                opt.zero_grad(); loss.backward(); opt.step()
32        with torch.no_grad(): pred=net(xte.to(dev)).cpu().numpy().ravel()
33    except RuntimeError:
34        seed_all(seed); net=make_model('mlp_tiny',tuple(xtr.shape[1:]),1); opt=torch.optim.Adam(net.parameters(),lr=cfg['lr'])
35        for _ in range(cfg['epochs']):
36            p=torch.randperm(len(xtr))
37            for st in range(0,len(p),cfg['batch']):
38                ix=p[st:st+cfg['batch']]; loss=nn.functional.mse_loss(net(xtr[ix]),target[ix]); opt.zero_grad(); loss.backward(); opt.step()
39        with torch.no_grad(): pred=net(xte).numpy().ravel()
40    metric=float(np.mean((pred-raw['yte'].ravel())**2)); qerr=float(np.mean((pred-raw['qte'].ravel())**2))
41    return {'metric':metric,'q_mse':qerr,'pred_mean':float(pred.mean())} if capture else metric
42
43def main():
44    # Promotion makes the track registered in the shared bench; never edit bench directly.
45    if TRACK not in __import__('bench').all_track_names():
46        if not validate_and_promote(HERE/'ising_teacher_track.py',TRACK,'exp2721 Kac-Ward Exact Teacher Stage-2'):
47            raise RuntimeError('custom track promotion failed')
48    reload_custom_tracks()
49    base=sweep_baseline(lambda c:(lambda s:train_one(s,c,False)),GRID)
50    idea_sweep=[]
51    for c in GRID:
52        idea_sweep.append({'cfg':c,'result':evaluate(lambda s,c=c:train_one(s,c,True),seeds=SEEDS)})
53    chosen=min(idea_sweep,key=lambda z:z['result']['mean']); idea=chosen['result']; icfg=chosen['cfg']
54    b0=train_one(0,base['best_cfg'],False,True); i0=train_one(0,icfg,True,True)
55    sig={'prediction':'exact soft conditional labels reduce trained-NN conditional probability MSE versus sampled labels','baseline_seed0':b0,'idea_seed0':i0,'q_mse_reduction':b0['q_mse']-i0['q_mse'],'confirmed':bool(i0['q_mse']<b0['q_mse'])}
56    report=make_report(TRACK,'mlp_tiny',base,idea,extra=sig)
57    report['idea_sweep']=idea_sweep
58    report['custom_track']={'name':TRACK,'file':'ising_teacher_track.py','domain':'sequence-level sampling'}
59    (HERE/'bench_report.json').write_text(json.dumps(report,indent=2)); print(json.dumps(report,indent=2))
60if __name__=='__main__': main()