Karar-git's picture
Add FINAL-2 pipeline, overnight search scripts and results (11 Nov 2026)
2c2dd6c verified
Raw History Blame Contribute Delete
3.79 kB
"""LP-FT with the number of fine-tuning steps chosen on Madrid.
tools/nnlab/lpft.py fixed STEPS = 60 in advance. Its Madrid check showed the gain of
whole-network fine-tuning growing with n, so this driver asks, on the Madrid
pseudo-target only (lab.madrid_split, the same cached source-part base network),
which of STEPS in {60, 150, 300, 600} is best, and then runs that one setting on
the Amsterdam protocol as tab_dann_rz_lpft_s{STEPS}.
Everything else (learning rates, replay, L2-SP, lam, epochs) is unchanged.
Amsterdam labels: only lab.shot_labels(lab.shots_for(...)) of the current draw.
"""
import json, sys, time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
import lab
import numpy as np
import lpft as L
import tab_nn
W = lab.W
GRID = (60, 150, 300, 600)
cache = lab.CACHE / "lpft"
sel = json.loads((lab.CACHE / "tab_nn" / "selection.json").read_text())
epochs, lam = int(sel["epochs"][L.KIND]), float(sel["lam"])
d = lab.load(official60=False)
t00 = time.time()
plain = {"lpft": L.METHODS["lpft"]}
sel_path = cache / "steps_selection.json"
if sel_path.exists():
S = json.loads(sel_path.read_text())
else:
src, tgt = lab.madrid_split(d["pm"])
Xs, Xt = tab_nn.TRANSFORM[L.INP](d["Xm"][src]), tab_nn.TRANSFORM[L.INP](d["Xm"][tgt])
ys, yt = d["ym"][src], d["ym"][tgt]
prior = np.array([(ys == c).mean() for c in lab.CLASSES])
state, _ = L.get_base(cache / f"{L.KIND}_{L.INP}_src_s{L.SEED}.pt", Xs, ys, Xt, epochs)
rows = []
for steps in GRID:
L.STEPS = steps
for n in L.CHECK_NS:
for rep in range(L.CHECK_REPS):
rng = np.random.default_rng(9000 + 100 * n + rep) # same draws as lpft.madrid_check
shot = np.concatenate([rng.choice(np.flatnonzero(yt == c), n, replace=False) for c in lab.CLASSES])
keep = np.setdiff1d(np.arange(len(yt)), shot)
P = L.lpft(state, Xt[shot], yt[shot], Xt[keep], Xs, ys, Xt, lam, 10_000 + 1000 * n + rep, plain)
f = W.macro_f1(yt[keep], W.decide(P["lpft"], prior))
rows.append(dict(steps=steps, n=n, rep=rep, f1=f))
print(f"[{time.time()-t00:6.0f}s] madrid steps={steps} n={n} rep={rep} f1={f:.4f}", flush=True)
import pandas as pd
df = pd.DataFrame(rows)
by = df.groupby(["steps", "n"]).f1.mean().unstack()
mean = df.groupby("steps").f1.mean()
best = int(mean.idxmax())
S = dict(grid=list(GRID), rows=rows, mean_by_steps={int(k): float(v) for k, v in mean.items()},
by_n={int(s): {int(n): float(v) for n, v in by.loc[s].items()} for s in by.index}, chosen=best,
rule="highest mean macro F1 over n in (5, 50, 200) x 3 draws on the Madrid pseudo-target")
sel_path.write_text(json.dumps(S, indent=1))
print("madrid selection:", S["mean_by_steps"], "by n:", S["by_n"], "-> chosen", S["chosen"], flush=True)
steps = int(S["chosen"])
if steps == 60:
print("60 steps stays best on Madrid: nothing new to run")
sys.exit(0)
L.STEPS = steps
name = f"tab_{L.KIND}_{L.INP}_lpft_s{steps}"
Xm, Xa = tab_nn.city_inputs(d, L.INP)
state, _ = L.get_base(cache / f"{L.KIND}_{L.INP}_s{L.SEED}.pt", Xm, d["ym"], Xa, epochs)
for n, rep in lab.draws():
if lab.have_pred(name, n, rep):
continue
t0 = time.time()
shot = lab.shots_for(d, n, rep)
P = L.lpft(state, Xa[shot], lab.shot_labels(d, shot), Xa, Xm, d["ym"], Xa, lam, 1000 * n + rep, plain)
lab.save_pred(name, n, rep, P["lpft"], dict(script="tools/nnlab/lpft_steps.py", steps=steps, steps_selection=S,
lam=lam, epochs=epochs, base="lpft.py base, seed 0"))
print(f"[{time.time()-t00:6.0f}s] {name} n={n} rep={rep} {time.time()-t0:.1f}s", flush=True)
print("done")