summaryrefslogtreecommitdiff
path: root/experiments/plot_contrastive_bias_b1.py
blob: 5fc70d1315889f695158619901d3c6e30e3bb8c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python3
"""Plot the audited B1 activity-bias result without rerunning analysis."""
import argparse
import json
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np


ROOT = Path(__file__).resolve().parents[1]
DEFAULT_GATE = ROOT / "results" / "contrastive_bias" / "b1_gate.json"
DEFAULT_OUT = ROOT / "results" / "contrastive_bias" / "b1_summary"


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--gate", type=Path, default=DEFAULT_GATE)
    parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
    args = parser.parse_args()
    with open(args.gate, encoding="utf-8") as handle:
        report = json.load(handle)
    rows = report["activity_table"]
    ratios = np.arange(len(rows))
    labels = [f"{row['ratio']:g}×" for row in rows]
    clean = report["clean_final_validation_accuracy"]

    plt.rcParams.update({
        "font.family": "DejaVu Sans", "font.size": 9,
        "axes.spines.top": False, "axes.spines.right": False,
    })
    figure, axes = plt.subplots(1, 2, figsize=(7.2, 2.65))

    ax = axes[0]
    ax.axhline(clean, color="#6b747b", linestyle="--", linewidth=1.2,
               label=f"clean DP: {clean:.2f}")
    ax.plot(ratios, [row["raw"] for row in rows], "X-", color="#c23b3b",
            linewidth=1.5, markersize=7, label="raw (nonfinite at epoch 1)")
    ax.plot(ratios, [row["innovation"] for row in rows], "o-",
            color="#0878a8", linewidth=1.8, markersize=5, label="innovation")
    ax.plot(ratios, [row["oracle"] for row in rows], "s-",
            color="#263640", linewidth=1.5, markersize=4.5, label="oracle")
    ax.set_xticks(ratios, labels)
    ax.set_ylim(0, 78)
    ax.set_xlabel("activity-dependent bias / clean teaching RMS")
    ax.set_ylabel("final validation accuracy (%)")
    ax.set_title("a  Task result", loc="left", fontweight="bold")
    ax.legend(frameon=False, fontsize=7.5, loc="lower right")

    ax = axes[1]
    width = 0.23
    ax.bar(ratios - width, [1, 1, 1], width, color="#c23b3b", label="raw")
    ax.bar(ratios, [20, 20, 20], width, color="#0878a8", label="innovation")
    ax.bar(ratios + width, [20, 20, 20], width, color="#263640", label="oracle")
    ax.set_xticks(ratios, labels)
    ax.set_ylim(0, 22)
    ax.set_yticks((0, 5, 10, 15, 20))
    ax.set_xlabel("activity-dependent bias / clean teaching RMS")
    ax.set_ylabel("epochs completed before nonfinite loss")
    ax.set_title("b  Stability", loc="left", fontweight="bold")
    ax.legend(frameon=False, fontsize=7.5, loc="lower right")
    ax.text(
        0.02, 0.95,
        "innovation residual bias ≤ 8.96×10⁻⁸\npredictor label observations = 0",
        transform=ax.transAxes, va="top", fontsize=7.5,
    )

    figure.suptitle(
        "Dual Prop under neuron-specific activity bias",
        x=0.08, ha="left", fontsize=12, fontweight="bold",
    )
    figure.tight_layout(rect=(0, 0, 1, 0.94))
    args.out.parent.mkdir(parents=True, exist_ok=True)
    figure.savefig(args.out.with_suffix(".pdf"), bbox_inches="tight")
    figure.savefig(args.out.with_suffix(".png"), dpi=220, bbox_inches="tight")
    plt.close(figure)


if __name__ == "__main__":
    main()