32 lines
2.3 KiB
Python
32 lines
2.3 KiB
Python
"""Train integer KNP readout on train only; choose lambda/quantization on validation."""
|
|
from pathlib import Path
|
|
import numpy as np,json,re,hashlib
|
|
R=Path.home()/'run/pets-knp'; C=R/'counts';M=R/'readout-v2'
|
|
if M.exists():raise RuntimeError('Refuse to overwrite readout')
|
|
M.mkdir()
|
|
def load(tag,n):
|
|
parts=[];nextrow=0
|
|
for p in sorted(C.glob(tag+'_*_counts.bin'),key=lambda p:int(p.stem.split('_')[-2])):
|
|
if not re.fullmatch(re.escape(tag)+r'_\d+_counts.bin',p.name):continue
|
|
first=int(p.stem.split('_')[-2]);assert first==nextrow and (C/f'{tag}_{first}.done').exists()
|
|
a=np.fromfile(p,np.int32).reshape(-1,800);parts.append(a);nextrow+=len(a)
|
|
assert nextrow==n,(tag,nextrow,n)
|
|
return np.concatenate(parts)
|
|
xt=np.concatenate([load('train',8000),load('train_flip',8000)]);xv=load('val',2000)
|
|
y=np.load(R/'data/train.npz')['labels'];yt=np.tile(y,2);yv=np.load(R/'data/val.npz')['labels'];
|
|
assert xt.min()>=0 and xt.max()<=640
|
|
mu=xt.mean(0);sd=xt.std(0)+1e-3;z=(xt-mu)/sd;zv=(xv-mu)/sd
|
|
A=z.T@z;v=z.T@(yt*2.-1); ym=(yt*2.-1).mean();candidates=[];best=None
|
|
for lam in (1,10,100,1000,10000):
|
|
sol=np.linalg.solve(A+lam*np.eye(800),v);w=sol/sd;b=ym-mu@w
|
|
ref=(xv@w+b>0).astype(int);print('lambda',lam,'float',float((ref==yv).mean()),flush=True)
|
|
for limit in (7,15,31):
|
|
scale=limit/abs(w).max();wq=np.rint(w*scale).astype(np.int32);bq=int(round(b*scale));margin=xv.astype(np.int64)@wq+bq
|
|
pred=(margin>0).astype(int);acc=float((pred==yv).mean());row={'lambda':lam,'weight_limit':limit,'validation_accuracy':acc,'ties':int((margin==0).sum()),'absolute_bound':int(640*abs(wq.astype(np.int64)).sum()+abs(bq))};candidates.append(row)
|
|
if row['absolute_bound']>=2**24:continue
|
|
if best is None or acc>best[0]:best=(acc,wq,bq,row)
|
|
assert best is not None
|
|
_,w,b,row=best;w.tofile(M/'weights.bin');np.array([b],np.int32).tofile(M/'bias.bin')
|
|
xv.tofile(R/'validation-counts.bin');np.savez_compressed(R/'training-counts.npz',train=xt,validation=xv)
|
|
row=dict(row);row.update(candidates=candidates,classes=['cat','dog'],tie_rule='margin0=>cat; no spike in either output',host='fixed quadrant spike pooling, packet multiplicity only; no learned arithmetic',detector_source='vehicle training only',model_sha256=hashlib.sha256((M/'weights.bin').read_bytes()+(M/'bias.bin').read_bytes()).hexdigest())
|
|
(M/'selection.json').write_text(json.dumps(row,indent=2)+'\n');print(json.dumps(row),flush=True)
|