Patch-Consensus Weak Residual Training / weak_consensus_experiment.py
Failed on benchmark
1import json, math
2from pathlib import Path
3import numpy as np
4from scipy.optimize import nnls
5
6SEED = 2184
7rng = np.random.default_rng(SEED)
8
9
10def lasso_cd(A, b, lam=0.04, iters=1200):
11 # objective 0.5||Ac-b||^2 + lam||c||_1, deterministic coordinate descent
12 A = np.asarray(A, float); b = np.asarray(b, float)
13 L = A.shape[1]; c = np.zeros(L)
14 col = (A*A).sum(0) + 1e-12
15 for _ in range(iters):
16 old = c.copy()
17 for k in range(L):
18 rho = A[:, k] @ (b - A @ c + A[:, k] * c[k])
19 z = abs(rho) - lam
20 c[k] = np.sign(rho) * max(z, 0.) / col[k]
21 if np.max(abs(c-old)) < 1e-9: break
22 return c
23
24
25def weak_patch_integral(n, sigma=1.0, repeats=300):
26 # Integral of a smooth function with iid observation noise; Monte Carlo weak integration.
27 vals=[]
28 for _ in range(repeats):
29 x = rng.random(n)
30 phi = 6*x*(1-x) # compact-like bump on patch, normalized below
31 truth = np.sin(2*np.pi*x) + .35*x
32 vals.append(np.mean(phi*(truth + sigma*rng.normal(size=n))) / np.mean(phi))
33 return np.std(vals, ddof=1)
34
35
36def consensus_error(p, m, trials=30000):
37 # binary local support decisions, modal support with random tie breaking
38 x = rng.random((trials, m)) < p
39 votes = x.sum(1)
40 return np.mean(votes < (m/2)) if m % 2 else np.mean(votes <= (m//2-1))
41
42
43def patch_regression_demo(npatch=80, q=24, noise=.22, lam=.045):
44 # Two candidate weak operators; true support is term 0. Each local patch gets q
45 # quadrature samples and noisy b. LASSO support is then pooled by modal consensus.
46 local = []
47 for j in range(npatch):
48 # normalized test-function integrations create mildly varying local designs
49 A = rng.normal(size=(3,2)); A[:,0] += 1.4
50 ctrue = np.array([1.0, 0.0])
51 b = A @ ctrue + noise*rng.normal(size=3)/math.sqrt(q)
52 c = lasso_cd(A, b, lam)
53 local.append(c)
54 local=np.array(local)
55 supports=np.abs(local)>0.16
56 true_support=np.array([True, False])
57 local_exact=np.all(supports == true_support[None, :], axis=1)
58 modal_support=np.sum(supports, axis=0) >= np.ceil(npatch/2)
59 modal_exact=bool(np.all(modal_support == true_support))
60 return float(np.mean(local_exact)), modal_exact, local
61
62
63def main():
64 global rng
65 # Prediction 1: weak integration averages independent noise, std proportional n^-1/2.
66 ns=np.array([8,16,32,64,128,256])
67 stds=np.array([weak_patch_integral(int(n)) for n in ns])
68 slope=float(np.polyfit(np.log(ns), np.log(stds), 1)[0])
69
70 # Prediction 2: local decisions only improve consensus when p > 1/2.
71 ps=[.40,.55,.70,.85]
72 ms=[3,7,15,31]
73 rows=[]
74 for p in ps:
75 for m in ms:
76 obs=consensus_error(p,m)
77 bound=math.exp(-2*m*(p-.5)**2)
78 rows.append({'p':p,'m':m,'observed_error':float(obs),'hoeffding_bound':float(bound)})
79
80 # Prediction 3: with a fixed local accuracy p=.7, more patches reduce errors;
81 # check monotonicity and compare the observed trend to the theoretical bound.
82 fixed=[r for r in rows if r['p']==.70]
83 monotonic=all(fixed[i]['observed_error'] >= fixed[i+1]['observed_error']-0.004 for i in range(len(fixed)-1))
84 below_bound=all(r['observed_error'] <= r['hoeffding_bound']+0.015 for r in rows if r['p']>.5)
85
86 # Secondary MVP comparison: local sparse fits versus modal support on noisy patches.
87 rng=np.random.default_rng(SEED+9)
88 reps=[]
89 for _ in range(100):
90 frac, modal, local=patch_regression_demo()
91 reps.append((frac,modal))
92 local_support=float(np.mean([x[0] for x in reps]))
93 consensus_support_accuracy=float(np.mean([x[1] for x in reps]))
94
95 result={
96 'seed':SEED,
97 'prediction_checks':{
98 'weak_noise_scaling':{'predicted_loglog_slope':-0.5,'observed_loglog_slope':slope,'tolerance':0.12,'passed':abs(slope+0.5)<0.12,'n':ns.tolist(),'std':stds.tolist()},
99 'consensus_transition':{'prediction':'majority improves for p>0.5 and worsens for p<0.5','rows':rows,'passed':(rows[0]['observed_error']>0.5 and rows[4]['observed_error']<0.5 and rows[8]['observed_error']<0.5)},
100 'patch_count_scaling':{'prediction':'error decreases with m for p=.70 and stays below Hoeffding upper bound','rows':fixed,'monotonic_with_sampling_tolerance':monotonic,'below_bound_with_sampling_tolerance':below_bound,'passed':monotonic and below_bound}
101 },
102 'secondary_mvp':{'local_exact_support_accuracy_mean':local_support,'modal_consensus_exact_accuracy':consensus_support_accuracy,'interpretation':'consensus converts noisy local support votes into a region-level decision'},
103 'all_mechanism_checks_passed':bool(abs(slope+0.5)<0.12 and rows[0]['observed_error']>0.5 and rows[4]['observed_error']<0.5 and monotonic and below_bound)
104 }
105 Path('results.json').write_text(json.dumps(result,indent=2))
106 print(json.dumps(result,indent=2))
107
108if __name__=='__main__': main()