Download code/reproduce/appendix/fid_sample_stability.py from coarse-grained-forecasting-benchmark/forecasting-models: direct link, hf CLI and curl.
- Browser
- Download file 5.93 kB
-
https://huggingface.co/coarse-grained-forecasting-benchmark/forecasting-models/resolve/main/code/reproduce/appendix/fid_sample_stability.py
- Command line
-
hf download hf://coarse-grained-forecasting-benchmark/forecasting-models/code/reproduce/appendix/fid_sample_stability.py
-
curl -L -o fid_sample_stability.py https://huggingface.co/coarse-grained-forecasting-benchmark/forecasting-models/resolve/main/code/reproduce/appendix/fid_sample_stability.py
5.93 kB
| """Appendix B.3: finite-sample stability of cFID and csFID (the ordering of the models and their relative gaps at N = 10,000). | |
| python reproduce/appendix/fid_sample_stability.py --system euler --samples direct_si=DIR --samples edm=DIR \\ | |
| --samples cascaded_si=DIR --out DIR [--floor-ns 1000,2500,5000] [--model-ns 2000,5000,10000] [--device cuda] | |
| floor rows FID(A_N, B_N), A and B disjoint halves of the truth ensemble (N <= 5,000: the bank holds 10,000 members) | |
| model rows FID(gen_N, truth_N) for each Table 2 model | |
| Members are the first N in the stored order, so every N is a nested subset; features are extracted once at the largest | |
| N. Writes OUT/sample_stability.{csv,json}. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| import csv | |
| import math | |
| import sys | |
| from collections import defaultdict | |
| from datetime import datetime, timezone | |
| from pathlib import Path | |
| import numpy as np | |
| REPO = Path(__file__).resolve().parents[2] | |
| sys.path.insert(0, str(REPO)) | |
| from reproduce.appendix.common import SystemInputs, add_system_args, both_features, extractors, write_json # noqa: E402 | |
| from bifurcation.fid import backend as BE # noqa: E402 | |
| from bifurcation.fid.evaluate import bank_members # noqa: E402 | |
| def main(argv=None) -> int: | |
| ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) | |
| add_system_args(ap) | |
| ap.add_argument("--floor-ns", default="1000,2500,5000") | |
| ap.add_argument("--model-ns", default="2000,5000,10000") | |
| a = ap.parse_args(argv) | |
| inp = SystemInputs(a) | |
| outdir = a.out.resolve(); outdir.mkdir(parents=True, exist_ok=True) | |
| ext, dev, layer_rec = extractors(inp.fid_cfg, a.device) | |
| batch = int(inp.fid_cfg.get("feature_batch", 200)) | |
| adapter, gids, t_idx = inp.adapter, inp.gids, inp.t_idx | |
| models = inp.models() | |
| floor_ns = [int(x) for x in a.floor_ns.split(",")] | |
| model_ns = [int(x) for x in a.model_ns.split(",")] | |
| nmax = max(model_ns + [2 * max(floor_ns)]) | |
| print(f"{a.system}: {len(gids)} test conditions, features at N = {nmax}") | |
| print("models: " + "; ".join(f"{m['label']} ({m['key']}, n* = {m['n_steps']})" for m in models)) | |
| print(f"floor N {floor_ns} (at most 5000: an independent floor at N needs 2N of the 10,000 members); model N {model_ns}\n") | |
| acc = defaultdict(lambda: defaultdict(list)) # acc[(row, N)][metric] -> per-condition values | |
| for g in gids: | |
| tv = bank_members(inp.bank, g, t_idx, nmax) | |
| imgs, _ = adapter.to_images(tv) | |
| tc, ts = both_features(imgs, ext, dev, batch) | |
| for N in floor_ns: | |
| acc[("floor (truth vs truth)", N)]["cfid"].append(BE.fid_from_features(tc[:N], tc[N:2 * N])) | |
| acc[("floor (truth vs truth)", N)]["sfid"].append(BE.fid_from_features(ts[:N], ts[N:2 * N])) | |
| line = (f" gid {g:4d} floor({floor_ns[-1]}) c{acc[('floor (truth vs truth)', floor_ns[-1])]['cfid'][-1]:6.2f}" | |
| f"/s{acc[('floor (truth vs truth)', floor_ns[-1])]['sfid'][-1]:7.2f}") | |
| for m in models: | |
| gi, _ = adapter.to_images(inp.generated(m["methods"][0], g, nmax)) | |
| gc, gs = both_features(gi, ext, dev, batch) | |
| for N in model_ns: | |
| acc[(m["label"], N)]["cfid"].append(BE.fid_from_features(gc[:N], tc[:N])) | |
| acc[(m["label"], N)]["sfid"].append(BE.fid_from_features(gs[:N], ts[:N])) | |
| line += f" | {m['label'][:20]} c{acc[(m['label'], model_ns[-1])]['cfid'][-1]:6.2f}/s{acc[(m['label'], model_ns[-1])]['sfid'][-1]:7.2f}" | |
| print(line, flush=True) | |
| def ms(v): | |
| x = np.asarray(v, float); return x.mean(), x.std(ddof=1) / math.sqrt(len(x)) | |
| rows = [] | |
| print(f"\n{'row':28s} {'N':>6s} {'cFID':>17s} {'csFID':>18s}") | |
| for (label, N), d in sorted(acc.items(), key=lambda kv: (kv[0][0], kv[0][1])): | |
| mc, sc = ms(d["cfid"]); msf, ssf = ms(d["sfid"]) | |
| rows.append({"row": label, "N": N, "n_ic": len(d["cfid"]), "cfid": mc, "cfid_sem": sc, "sfid": msf, "sfid_sem": ssf, | |
| "per_gid_cfid": {int(g): float(v) for g, v in zip(gids, d["cfid"])}, | |
| "per_gid_sfid": {int(g): float(v) for g, v in zip(gids, d["sfid"])}}) | |
| print(f"{label:28s} {N:6d} {mc:8.3f} +- {sc:6.3f} {msf:9.3f} +- {ssf:6.3f}") | |
| print("\nordering and relative gaps across N (model rows only)") | |
| summary = {} | |
| for metric, key in (("cFID", "cfid"), ("csFID", "sfid")): | |
| summary[metric] = {} | |
| for N in model_ns: | |
| vals = {r["row"]: r[key] for r in rows if r["N"] == N and not r["row"].startswith("floor")} | |
| order = sorted(vals, key=vals.get) | |
| best = vals[order[0]] | |
| summary[metric][N] = {"order": order, "values": vals, "ratio_to_best": {k: vals[k] / best for k in order}} | |
| print(f" {metric} N={N:6d} order: {' < '.join(order)} ratios to best: " | |
| + ", ".join(f"{k}={v:.2f}" for k, v in summary[metric][N]["ratio_to_best"].items())) | |
| write_json(outdir / "sample_stability.json", {"at": datetime.now(timezone.utc).isoformat(timespec="seconds"), "system": a.system, | |
| "gids": gids, "t_idx": t_idx, "floor_ns": floor_ns, "model_ns": model_ns, | |
| "models": models, "adapter": adapter.params, "layer": layer_rec, "pins": BE.pins(), | |
| "rows": rows, "stability": summary}) | |
| with open(outdir / "sample_stability.csv", "w", newline="") as fh: | |
| w = csv.writer(fh); w.writerow(["row", "N", "n_ic", "cfid", "cfid_sem", "sfid", "sfid_sem"]) | |
| for r in rows: | |
| w.writerow([r["row"], r["N"], r["n_ic"], r["cfid"], r["cfid_sem"], r["sfid"], r["sfid_sem"]]) | |
| print(f"\nwrote {outdir / 'sample_stability.csv'}\n {outdir / 'sample_stability.json'}") | |
| return 0 | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |