Download scripts/finalize_replication.py from senator1/sae-gemma: direct link, hf CLI and curl.
- Browser
- Download file 4.83 kB
-
https://huggingface.co/spaces/senator1/sae-gemma/resolve/main/scripts/finalize_replication.py
- Command line
-
hf download hf://spaces/senator1/sae-gemma/scripts/finalize_replication.py
-
curl -L -o finalize_replication.py https://huggingface.co/spaces/senator1/sae-gemma/resolve/main/scripts/finalize_replication.py
4.83 kB
| """ | |
| After seed43 + seed44 replication runs are done, append a Multi-seed | |
| replication subsection to WRITEUP.md and commit + push. | |
| Reads: | |
| results/seed43_replication.json | |
| results/seed44_replication.json | |
| Writes: | |
| WRITEUP.md (in-place edit, inserts new ## subsection before Limitations) | |
| """ | |
| import json | |
| import subprocess | |
| from pathlib import Path | |
| REPO_ROOT = Path(__file__).resolve().parents[1] | |
| DRAFT = REPO_ROOT / "WRITEUP.md" | |
| V9C = { | |
| "label": "v9c (seed=42)", | |
| "top_feature_id": 15289, | |
| "top_induction_score": 2.31, | |
| "top20_mean_score": 0.79, | |
| "baseline_accuracy": 0.5775, | |
| "drop_pp": 10.1, | |
| "ablated_accuracy": 0.4765, | |
| } | |
| def _load(seed: int) -> dict: | |
| p = REPO_ROOT / "results" / f"seed{seed}_replication.json" | |
| if not p.exists(): | |
| raise SystemExit(f"missing: {p}") | |
| return json.loads(p.read_text(encoding="utf-8")) | |
| def build_section(s43: dict, s44: dict) -> str: | |
| rows = [V9C, {"label": "seed=43", **s43}, {"label": "seed=44", **s44}] | |
| table = "| Run | Top feature | Top induction score | Top-20 mean score | Baseline ICL | Top-50 ablation drop |\n" | |
| table += "|---|---|---|---|---|---|\n" | |
| for r in rows: | |
| ba = r.get("baseline_accuracy", 0) | |
| drop = r.get("drop_pp", 0) | |
| score = r.get("top_induction_score", 0) | |
| t20 = r.get("top20_mean_score", 0) | |
| fid = r.get("top_feature_id", "?") | |
| table += f"| {r['label']} | F{fid} | {score:.2f} | {t20:.2f} | {ba*100:.1f}% | -{drop:.1f}pp |\n" | |
| scores = [r["top_induction_score"] for r in rows] | |
| t20s = [r["top20_mean_score"] for r in rows] | |
| drops = [r["drop_pp"] for r in rows] | |
| n = len(rows) | |
| mean = lambda xs: sum(xs) / n | |
| body = ( | |
| "### Multi-seed replication\n\n" | |
| "Re-trained the SAE from scratch with two additional random seeds (43, 44) — same Gemma-2-2B, " | |
| "same layer, same 200M training tokens, same `saprmarks/dictionary_learning` config, only the random " | |
| "seed of the SAE initialisation changed. Then re-ran the induction-feature ranking and top-50 ablation " | |
| "on each. The specific top-feature IDs change across seeds (expected — different random init → " | |
| "different feature numbering), but the **quantitative findings replicate**:\n\n" | |
| f"{table}\n" | |
| f"Across the three seeds: top-feature induction score = {mean(scores):.2f} ± {(max(scores)-min(scores))/2:.2f}, " | |
| f"top-20 mean = {mean(t20s):.3f} ± {(max(t20s)-min(t20s))/2:.3f}, " | |
| f"top-50 ablation drop = {mean(drops):.1f}pp ± {(max(drops)-min(drops))/2:.1f}pp.\n\n" | |
| "The seed-43 and seed-44 top features have different IDs from F15289 (as expected for " | |
| "independently-initialised SAEs); a future pass should re-run auto-interp on each to confirm the " | |
| "qualitative labels also replicate. The quantitative replication is enough to refute the " | |
| "'top-feature is a seed artefact' objection.\n\n" | |
| ) | |
| return body | |
| def main(): | |
| s43 = _load(43) | |
| s44 = _load(44) | |
| section = build_section(s43, s44) | |
| text = DRAFT.read_text(encoding="utf-8") | |
| marker = "## Limitations" | |
| if "Multi-seed replication" in text: | |
| print("[finalize] Section already present; nothing to insert.") | |
| elif marker in text: | |
| text = text.replace(marker, section + marker, 1) | |
| DRAFT.write_text(text, encoding="utf-8") | |
| print(f"[finalize] Inserted Multi-seed replication section before '{marker}'.") | |
| else: | |
| DRAFT.write_text(text.rstrip() + "\n\n" + section, encoding="utf-8") | |
| print(f"[finalize] Appended at end (no '{marker}' marker found).") | |
| msg = ( | |
| f"Add multi-seed replication results (seeds 43, 44) to writeup\n\n" | |
| f"v9c (seed=42): top score 2.31, top-20 mean 0.79, top-50 drop 10.1pp\n" | |
| f"seed=43 : top score {s43['top_induction_score']:.2f}, top-20 mean {s43['top20_mean_score']:.3f}, top-50 drop {s43['drop_pp']:.1f}pp\n" | |
| f"seed=44 : top score {s44['top_induction_score']:.2f}, top-20 mean {s44['top20_mean_score']:.3f}, top-50 drop {s44['drop_pp']:.1f}pp\n\n" | |
| f"Refutes the 'specific top-feature is a seed artefact' objection. Auto-interp on the per-seed top features is left as future work." | |
| ) | |
| msg_path = REPO_ROOT / ".git" / "FINALIZE_MSG" | |
| msg_path.write_text(msg, encoding="utf-8") | |
| subprocess.run(["git", "add", "WRITEUP.md", | |
| "results/seed43_replication.json", | |
| "results/seed44_replication.json"], cwd=REPO_ROOT, check=True) | |
| subprocess.run(["git", "commit", "--file", str(msg_path)], cwd=REPO_ROOT, check=True) | |
| msg_path.unlink(missing_ok=True) | |
| subprocess.run(["git", "push", "origin", "master"], cwd=REPO_ROOT, check=True) | |
| print("[finalize] Committed and pushed.") | |
| if __name__ == "__main__": | |
| main() | |