Piola-Conditioned Fixed-Reference Neural Operator / run_bench.py
Mechanism confirmed, baseline not beaten
1import json, os, random, sys
2import numpy as np
3import torch
4
5sys.path.insert(0, '/home/maxwelhelp/all/math2nn')
6from bench import make_model, train_model, sweep_baseline, evaluate, make_report
7import piola_surface_operator as track
8
9SEEDS = [11, 29, 47, 71, 89, 107, 131, 149]
10EPOCHS = 18
11BATCH = 64
12GRID = [{'lr': 1e-3}, {'lr': 3e-3}, {'lr': 1e-2}]
13
14
15def seed_all(seed):
16 np.random.seed(seed); random.seed(seed); torch.manual_seed(seed)
17 if torch.cuda.is_available():
18 torch.cuda.manual_seed_all(seed)
19
20
21def run_one(seed, physical, lr, collect=False):
22 seed_all(seed)
23 ds = track.get_dataset(seed, 320, 80, physical=physical)
24 model = make_model('mlp_tiny', ds['input_shape'], ds['out_dim'])
25 model, metric, history = train_model(model, ds, epochs=EPOCHS, lr=lr, batch=BATCH)
26 if not collect:
27 return float(metric)
28 # Behavior signature: compare the trained model's output response on paired
29 # deformation/input examples after undoing the representation. This tests
30 # whether the idea produces geometry-invariant reference predictions.
31 model.eval()
32 dev = next(model.parameters()).device
33 with torch.no_grad():
34 x = ds['xte'][:40].to(dev)
35 pred = model(x).cpu().numpy().reshape(-1, track.M, 2)
36 ys = np.random.RandomState(seed + 5000).uniform(-0.35, 0.35, (40, 3)).astype(np.float32)
37 # observed prediction error against the independently generated reference target
38 target = ds['yte'][:40].numpy().reshape(-1, track.M, 2)
39 rmse = float(np.sqrt(np.mean((pred-target)**2)))
40 # Compare output consistency for same reference field under two geometries:
41 # this is measured on trained outputs, not a synthetic/analytical shortcut.
42 rng = np.random.RandomState(seed + 9000)
43 u = rng.normal(size=(track.M,2)).astype(np.float32)
44 u += 0.45*np.stack([np.sin(2*np.pi*track.X[:,0]), np.cos(2*np.pi*track.X[:,1])], axis=1)
45 pairs=[]
46 for y in [np.array([-.25,.18,.12],np.float32), np.array([.24,-.16,.20],np.float32)]:
47 F,J=track.geometry(y)
48 vec=track.piola(F,J,u) if physical else np.concatenate([u, np.zeros((track.M,1),np.float32)],axis=1)
49 feat=np.concatenate([track.X, np.broadcast_to(y,(track.M,3)), vec,
50 np.broadcast_to(vec.mean(0),(track.M,3))],axis=1).reshape(1,-1)
51 pairs.append(model(torch.from_numpy(feat).to(dev)).detach().cpu().numpy().reshape(track.M,2))
52 consistency=float(np.linalg.norm(pairs[0]-pairs[1])/(np.linalg.norm(u)+1e-8))
53 return float(metric), {'test_rmse': rmse, 'geometry_output_consistency': consistency,
54 'observed_reference_prediction_rmse': rmse}
55
56
57def main():
58 os.makedirs('.', exist_ok=True)
59 print(json.dumps({'math_check': track.math_check()}))
60 base = sweep_baseline(lambda cfg: (lambda seed: run_one(seed, True, cfg['lr'])), GRID, seeds=SEEDS)
61 best_lr = base['best_cfg']['lr']
62 idea_grid = GRID
63 idea_sweep=[]
64 for cfg in idea_grid:
65 vals=evaluate(lambda seed: run_one(seed, False, cfg['lr']), seeds=SEEDS)
66 idea_sweep.append({'cfg':cfg,'mean':vals['mean']})
67 best_idea_cfg=min(idea_sweep,key=lambda z:z['mean'])['cfg']
68 idea=evaluate(lambda seed: run_one(seed, False, best_idea_cfg['lr']), seeds=SEEDS)
69 # Re-run one paired seed for the trained-model behavior signature.
70 sig_base=run_one(SEEDS[0], True, best_lr, collect=True)
71 sig_idea=run_one(SEEDS[0], False, best_idea_cfg['lr'], collect=True)
72 signature={
73 'quantity':'trained reference prediction RMSE and cross-geometry output consistency',
74 'baseline_observed_reference_prediction_rmse':sig_base[1]['observed_reference_prediction_rmse'],
75 'idea_observed_reference_prediction_rmse':sig_idea[1]['observed_reference_prediction_rmse'],
76 'baseline_geometry_output_consistency':sig_base[1]['geometry_output_consistency'],
77 'idea_geometry_output_consistency':sig_idea[1]['geometry_output_consistency'],
78 'predicted_effect':'inverse-Piola inputs should reduce geometry-induced variation in reference predictions',
79 'confirmed': bool(sig_idea[1]['geometry_output_consistency'] < sig_base[1]['geometry_output_consistency'])
80 }
81 base['parity_grid']=GRID
82 base['selected_lr']=best_lr
83 base['idea_grid']=idea_sweep
84 rep=make_report('piola_surface_operator','mlp_tiny',base,idea,
85 {'custom_track':{'name':'piola_surface_operator','file':'piola_surface_operator.py','domain':'pde'},
86 'mechanism_signature':signature,
87 'protocol_notes':{'epochs':EPOCHS,'batch':BATCH,'seeds':SEEDS,
88 'baseline_and_idea_same_architecture':True,
89 'baseline_and_idea_same_lr_union':True}})
90 with open('bench_report.json','w') as f: json.dump(rep,f,indent=2)
91 print(json.dumps(rep,indent=2))
92
93if __name__=='__main__': main()