our_knp/objects/final_fresh_test.py
int c2ac33767d One-time fresh-test evaluation of object pipelines
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:43:38 +03:00

72 lines
3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""One-time evaluation on the fresh cats/dogs test (600 images). Settings were fixed on validation before.
A: learned features K 800 with contrast division, standardised, ridge lam 300 (no spikes; upper reference).
B: K 800 without contrast division (folds into neuron weights), alpha 0.25, ridge lam 300.
C: fully spiking, exact step-by-step simulation (spiking_pipeline.py): layer-1 threshold 108.08, readout ridge
lam 1e6 on exact layer-1 spike counts, readout neuron threshold 4 × median per-step input (unit from validation).
usage: ~/anvenv/bin/python final_fresh_test.py
"""
import json
import sys
import numpy as np
sys.path.insert(0, "/mnt/c/knp/objects")
import kmeans_features as kf # noqa: E402
import spiking_pipeline as sp # noqa: E402
root = "/home/int/run/cats-dogs"
fresh = np.load(f"{root}/data-v3/fresh_test.npz")
xf, yf = fresh["rgb"], fresh["labels"].astype(int)
tr, va = np.load(f"{root}/data-v3/train.npz"), np.load(f"{root}/data-v3/val.npz")
yt = np.r_[tr["labels"], tr["labels"]].astype(int)
yv = va["labels"].astype(int)
res = {}
def ridge(f, y, lam):
f = np.hstack([f, np.ones((len(f), 1), np.float32)])
return np.linalg.solve(f.T @ f + lam * np.eye(f.shape[1]), f.T @ (np.eye(2)[y] * 2 - 1))
def acc(w, f, y):
f = np.hstack([f, np.ones((len(f), 1), np.float32)])
return 100 * ((f @ w).argmax(1) == y).mean()
# A
d = np.load(f"{root}/v3_k800.npz")
model = {k: d[k] for k in ("mean", "zca", "d")}
kf.CONTRAST_DIVIDE = True
mu, sd = d["Ft"].mean(0), d["Ft"].std(0) + 1e-3
w = ridge((d["Ft"] - mu) / sd, yt, 300)
res["A"] = {"val": acc(w, (d["Fv"] - mu) / sd, yv), "fresh": acc(w, (kf.encode(xf, model) - mu) / sd, yf)}
print("A", res["A"], flush=True)
# B
d = np.load(f"{root}/v3_k800_lin.npz")
model = {k: d[k] for k in ("mean", "zca", "d")}
kf.CONTRAST_DIVIDE = False
ft = np.vstack([kf.encode(tr["rgb"], model, alpha=0.25), kf.encode(tr["rgb"][:, :, :, ::-1], model, alpha=0.25)])
mu, sd = ft.mean(0), ft.std(0) + 1e-3
w = ridge((ft - mu) / sd, yt, 300)
res["B"] = {"val": acc(w, (kf.encode(va["rgb"], model, alpha=0.25) - mu) / sd, yv),
"fresh": acc(w, (kf.encode(xf, model, alpha=0.25) - mu) / sd, yf)}
print("B", res["B"], flush=True)
# C
s = np.load(f"{root}/spiking_v3_k800.npz")
ct, sv = s["ct"], s["sv"]
f = lambda c: np.hstack([c.astype(np.float32), np.ones((len(c), 1), np.float32)])
sol = np.linalg.solve(f(ct).T @ f(ct) + 1e6 * np.eye(ct.shape[1] + 1), f(ct).T @ (s["yt"] * 2 - 1.0))
rq = np.rint(sol / np.abs(sol).max() * 255).astype(np.int64)
bias = int(np.rint(rq[-1] / sp.ACTIVE))
unit = float(np.median(np.abs(sv[:, :sp.ACTIVE].reshape(-1, sv.shape[-1]) @ rq[:-1] + bias))) + 1
thr = 4 * unit
sf, tf = sp.layer1_counts(xf, s["wq"], s["bq"], float(s["thr1"]), per_step=True)
res["C"] = {"val": 100 * (sp.readout_neuron(sv, rq[:-1], bias, thr) == yv).mean(),
"fresh": 100 * (sp.readout_neuron(sf, rq[:-1], bias, thr) == yf).mean(),
"layer1_spikes_per_image": int(tf.mean()), "readout_threshold": thr}
print("C", res["C"], flush=True)
json.dump(res, open(f"{root}/final_fresh_test.json", "w"), indent=1)