Download src/sudoku_rsweep.py from GOVINDFROM/parallel-consistent-masked-diffusion: direct link, hf CLI and curl.
- Browser
- Download file 3.15 kB
-
https://huggingface.co/GOVINDFROM/parallel-consistent-masked-diffusion/resolve/main/src/sudoku_rsweep.py
- Command line
-
hf download hf://GOVINDFROM/parallel-consistent-masked-diffusion/src/sudoku_rsweep.py
-
curl -L -o sudoku_rsweep.py https://huggingface.co/GOVINDFROM/parallel-consistent-masked-diffusion/resolve/main/src/sudoku_rsweep.py
3.15 kB
| """Does deep supervision make the recurrence EXTRAPOLATE past its training depth? | |
| The claim behind supervising every recurrence is that it forces each application | |
| of the shared block to be a valid one-step refinement. If that holds, the map is | |
| iterable beyond where it was fit, and running more recurrences at inference than | |
| at training should keep helping - or at least not collapse. | |
| This is free: no retraining, only re-evaluating trained checkpoints at different | |
| recurrence counts. A model whose accuracy peaks exactly at its training depth and | |
| degrades past it has learned one entangled R-step function rather than a | |
| repeatable refinement step. | |
| """ | |
| import argparse, glob, json, os, sys | |
| from collections import defaultdict | |
| import numpy as np | |
| import torch | |
| sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | |
| from model import RecurrentDenoiser | |
| import diffusion as dfn | |
| from sudoku import CELLS, SudokuTokenizer | |
| p = argparse.ArgumentParser() | |
| p.add_argument("--hard", default="data/sudoku_hard") | |
| p.add_argument("--runs", default="runs") | |
| p.add_argument("--pattern", default="rec1-*") | |
| p.add_argument("--passes", type=int, default=16) | |
| p.add_argument("--eval_bs", type=int, default=250) | |
| p.add_argument("--out", default="figures/sudoku_rsweep.json") | |
| a = p.parse_args() | |
| dev = "cuda" if torch.cuda.is_available() else "cpu" | |
| tok = SudokuTokenizer() | |
| P = np.load(os.path.join(a.hard, "test_puz.npy")) | |
| S = np.load(os.path.join(a.hard, "test_sol.npy")) | |
| Pt, St = torch.from_numpy(P), torch.from_numpy(S - 1) | |
| blank = Pt == 0 | |
| res = defaultdict(dict) | |
| for d in sorted(glob.glob(os.path.join(a.runs, a.pattern))): | |
| rf = os.path.join(d, "result.json") | |
| if not (os.path.exists(rf) and os.path.exists(os.path.join(d, "model.pt"))): | |
| continue | |
| cfg = json.load(open(rf))["args"] | |
| if not cfg.get("recurrent"): | |
| continue | |
| m = RecurrentDenoiser(len(tok), cfg["d"], cfg["layers"], cfg["heads"], cfg["pe"], | |
| max_len=CELLS + 8, recurrences=cfg["R"]).to(dev) | |
| m.load_state_dict(torch.load(os.path.join(d, "model.pt"), map_location=dev)) | |
| m.eval() | |
| name = os.path.basename(d) | |
| trained_R = cfg["R"] | |
| print(f"\n--- {name} (trained with R={trained_R})", flush=True) | |
| print(f" {'R at inference':>16}{'board':>10}", flush=True) | |
| for R in (1, 2, 4, 8, 16, 32, 64, 128): | |
| m.recurrences = R | |
| preds = [] | |
| with torch.no_grad(): | |
| for i in range(0, len(Pt), a.eval_bs): | |
| gold = St[i:i + a.eval_bs].to(dev) | |
| bl = blank[i:i + a.eval_bs].to(dev) | |
| x = torch.where(bl, torch.full_like(gold, tok.mask), gold) | |
| y, _ = dfn.fixed_k_decode(m, x, tok, dev, a.passes, fillable=bl) | |
| preds.append(y.cpu().numpy() + 1) | |
| acc = float((np.concatenate(preds) == S).all(axis=1).mean()) | |
| res[name][R] = acc | |
| flag = " <- trained here" if R == trained_R else "" | |
| print(f" {R:>16}{acc*100:>9.2f}%{flag}", flush=True) | |
| del m | |
| torch.cuda.empty_cache() | |
| os.makedirs(os.path.dirname(a.out) or ".", exist_ok=True) | |
| json.dump(res, open(a.out, "w"), indent=2) | |
| print(f"\nwrote {a.out}") | |