| """ |
| Per-cell difference of two gradient-ascent heatmaps: Δ = A − B (per alpha, per (l,l')). |
| |
| A and B are the JSON outputs of gradient_ascent.py (each {alphas, delta:{alpha:matrix}}). |
| Use to compare two models/conditions, e.g. base induction (A) minus LoRA induction (B): |
| positive cell ⇒ A's bathroom→toilet influence is larger there (LoRA reduced it). |
| |
| Plots with the shared plot_heatmaps (normal | meannorm), same as gradient_ascent.py. |
| """ |
| import argparse |
| import json |
|
|
| import numpy as np |
| from mechanistic_interp.gradient_ascent import plot_heatmaps |
|
|
|
|
| def load(path): |
| d = json.load(open(path)) |
| mats = {float(a): np.array([[np.nan if v is None else v for v in row] for row in M]) |
| for a, M in d["delta"].items()} |
| return mats, d |
|
|
|
|
| def main(): |
| ap = argparse.ArgumentParser() |
| ap.add_argument("--json_a", required=True, help="minuend JSON (A)") |
| ap.add_argument("--json_b", required=True, help="subtrahend JSON (B)") |
| ap.add_argument("--out", required=True) |
| ap.add_argument("--plot_mode", default="meannorm", choices=["normal", "meannorm"]) |
| ap.add_argument("--title", default=None) |
| args = ap.parse_args() |
|
|
| A, da = load(args.json_a) |
| B, db = load(args.json_b) |
| alphas = sorted(set(A) & set(B)) |
| if not alphas: |
| raise SystemExit(f"No common alphas: A={sorted(A)} B={sorted(B)}") |
| diff = {a: A[a] - B[a] for a in alphas} |
| nA, nB = da.get("n_images", "?"), db.get("n_images", "?") |
| title = args.title or f"A − B (A: n={nA}, B: n={nB}) per cell — {args.plot_mode}" |
| |
| alphas_disp = [int(a) if float(a).is_integer() else a for a in alphas] |
| plot_heatmaps({ad: diff[a] for a, ad in zip(alphas, alphas_disp)}, alphas_disp, |
| args.out, title=title, mode=args.plot_mode, cbar_label="Δ_A − Δ_B") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|