Pre-Training Depth Feasibility Certificates / bench_depth_certificate.py
Failed on benchmark
1from __future__ import annotations
2import json, sys
3from pathlib import Path
4import numpy as np
5import torch
6from torch import nn
7sys.path.insert(0, '/home/maxwelhelp/all/math2nn')
8import bench
9
10SEEDS = tuple(range(8))
11DEPTHS = (1, 2, 3, 4)
12LRS = (0.0015, 0.003, 0.006)
13EPOCHS = 12
14BATCH = 128
15WIDTH = 64
16
17class VariableMLP(nn.Module):
18 def __init__(self, input_dim, depth, width=WIDTH):
19 super().__init__()
20 layers, d = [], input_dim
21 for _ in range(depth):
22 layers += [nn.Linear(d, width), nn.ReLU()]
23 d = width
24 layers.append(nn.Linear(d, 1))
25 self.net = nn.Sequential(*layers)
26 def forward(self, x):
27 return self.net(x.reshape(x.shape[0], -1))
28
29def make_model(ds, depth):
30 return VariableMLP(int(np.prod(tuple(ds['xtr'].shape[1:]))), int(depth))
31
32def train_metric(ds, depth, lr, return_model=False):
33 model = make_model(ds, depth)
34 net, metric, _ = bench.train_model(model, ds, epochs=EPOCHS, lr=float(lr),
35 batch=BATCH, weight_decay=0.0, log=lambda *_: None)
36 if metric is None:
37 raise RuntimeError('bench training failed')
38 return (float(metric), net) if return_model else float(metric)
39
40def eval_cfg(cfg, seeds=SEEDS):
41 vals = []
42 for seed in seeds:
43 torch.manual_seed(10000 + seed)
44 np.random.seed(20000 + seed)
45 ds = bench.get_dataset('tabular', seed, n_train=400, n_test=400)
46 vals.append(train_metric(ds, cfg['depth'], cfg['lr']))
47 return {'per_seed': vals, 'mean': float(np.mean(vals)),
48 'std': float(np.std(vals, ddof=1))}
49
50def baseline_train(cfg):
51 return lambda seed: train_metric(bench.get_dataset('tabular', seed, 400, 400), cfg['depth'], cfg['lr'])
52
53def calibration(seed=9001):
54 ds = bench.get_dataset('tabular', seed, n_train=400, n_test=400)
55 # Calibration discrepancy is validation MSE to a fixed high-precision teacher.
56 torch.manual_seed(30000 + seed)
57 teacher, _ = train_metric(ds, 4, 0.003, return_model=True)
58 del teacher
59 rows = []
60 for d in DEPTHS:
61 torch.manual_seed(31000 + d)
62 err = train_metric(ds, d, 0.003)
63 rows.append((d, err))
64 # Fit E(d)=floor+C_syn/d; residual margin gives conservative [L,U].
65 X = np.array([[1.0, 1.0/d] for d, _ in rows])
66 y = np.array([e for _, e in rows])
67 coef = np.linalg.lstsq(X, y, rcond=None)[0]
68 resid = y - X @ coef
69 margin = max(0.002, 2.0 * float(np.std(resid)))
70 return {'floor_L': float(coef[0]-margin), 'floor_U': float(coef[0]+margin),
71 'C_syn': float(max(0.0, coef[1])), 'rows': rows,
72 'residual_std': float(np.std(resid))}
73
74def main():
75 # Search-space parity: every idea lr/depth pair is included in baseline grid.
76 grid = [{'depth': d, 'lr': lr} for d in DEPTHS for lr in LRS]
77 base = bench.sweep_baseline(baseline_train, grid, seeds=SEEDS[:4])
78 base['full'] = eval_cfg(base['best_cfg'], SEEDS)
79 cal = calibration()
80 eps = float(base['full']['mean'])
81 candidates = []
82 for d in DEPTHS:
83 radius = cal['C_syn'] / d + cal['floor_U'] - cal['floor_L']
84 upper = cal['floor_U'] + radius
85 lower = cal['floor_L'] - radius
86 candidates.append((upper, d, lower))
87 feasible = [x for x in candidates if x[0] <= eps]
88 chosen_depth = min((x[1] for x in feasible), default=4)
89 # Same-size idea sweep at the baseline best lr and two nearby union-grid lrs.
90 idea_grid = [{'depth': chosen_depth, 'lr': lr} for lr in LRS]
91 idea_trials = [{'cfg': c, 'result': eval_cfg(c, SEEDS[:4])} for c in idea_grid]
92 best = min(idea_trials, key=lambda z: z['result']['mean'])['cfg']
93 idea = eval_cfg(best, SEEDS)
94 comparison = bench.compare_results(base['full'], idea)
95 # NN-scale mechanism signature: observed fitted depth law from trained models.
96 observed = []
97 for d in DEPTHS:
98 r = eval_cfg({'depth': d, 'lr': best['lr']}, SEEDS[:2])
99 observed.append((d, r['mean']))
100 slope = float(np.polyfit(np.log([d for d,_ in observed]), np.log(np.maximum([e for _,e in observed],1e-12)), 1)[0])
101 signature = {'predicted_radius_depth_exponent': -1.0,
102 'observed_test_error_depth_slope': slope,
103 'predicted_vs_observed_tolerance': 0.35,
104 'confirmed': bool(abs(slope + 1.0) <= 0.35),
105 'observed_depth_errors': observed,
106 'note': 'Measured on independently trained benchmark models.'}
107 report = bench.make_report('tabular', 'variable_mlp', base, idea,
108 {'certificate_calibration': cal, 'candidate_certificates': candidates,
109 'chosen_depth': chosen_depth, 'idea_grid': idea_trials,
110 'mechanism_signature': signature})
111 report['mechanism_signature'] = signature
112 report['bench_report'] = {'track': 'tabular', 'model': 'variable_mlp',
113 'calibration': cal, 'chosen_depth': chosen_depth}
114 Path('bench_report.json').write_text(json.dumps(report, indent=2))
115 print(json.dumps(report, indent=2))
116
117if __name__ == '__main__':
118 main()