IMM Stale-Feedback Detector / mini_control.py
Failed on benchmark
1import json, math
2import numpy as np
3
4# Scalar quadratic: f(x)=x^2/2. A worker applies a gradient from d steps ago.
5# The IMM observes x with Gaussian noise and controls the learning rate after alarm.
6def detect(obs, q=.002, r=.01, D=4, persistence=.985, threshold=.01):
7 m=D+1; T=np.full((m,m),(1-persistence)/(m-1)); np.fill_diagonal(T,persistence)
8 pi=np.ones(m)/m; hist=[0.]*(D+1); alarms=0
9 out=[]
10 for y in obs:
11 hist.append(hist[-1]); hist=hist[-D-1:]
12 c=T.T@pi; means=np.asarray(hist[::-1])
13 ll=-.5*((y-means)**2/r+math.log(2*math.pi*r))
14 u=c*np.exp(ll-ll.max()); pi=u/u.sum(); alarms=alarms+1 if pi[0]<=threshold else 0
15 out.append((pi.copy(), alarms>=3))
16 return out
17
18def run(lr, delay, controlled, seed):
19 rng=np.random.default_rng(seed); n=250; x=[2.0]*(delay+1); ys=[]
20 # First 30 clean observations calibrate the delay monitor; attack thereafter.
21 for t in range(n):
22 d=0 if t<30 else delay
23 g=x[-1-d]
24 x.append(x[-1]-lr*g if not controlled else x[-1])
25 ys.append(x[-1]+rng.normal(0,.1))
26 decisions=detect(ys)
27 # Re-run dynamics with detector decisions causally.
28 x=[2.0]*(delay+1); lr_now=lr; alarm_step=None
29 for t in range(n):
30 if controlled and decisions[t][1] and alarm_step is None:
31 alarm_step=t+1; lr_now=lr/4
32 d=0 if t<30 else delay
33 x.append(x[-1]-lr_now*x[-1-d])
34 return float(.5*x[-1]**2), alarm_step, max(abs(v) for v in x)
35
36def main():
37 rows=[]
38 for lr in (.8,1.0,1.2):
39 b=[run(lr,2,False,s) for s in range(20)]
40 i=[run(lr,2,True,s) for s in range(20)]
41 rows.append({'lr':lr,'baseline_final_loss':float(np.median([z[0] for z in b])),
42 'imm_final_loss':float(np.median([z[0] for z in i])),
43 'baseline_max_abs_x':float(np.median([z[2] for z in b])),
44 'imm_max_abs_x':float(np.median([z[2] for z in i])),
45 'imm_alarm_median':float(np.median([z[1] for z in i if z[1] is not None]))})
46 print(json.dumps({'quadratic_delayed_feedback':rows,'steps':250,'attack_starts':30,'replicates':20},indent=2))
47if __name__=='__main__': main()