diff options
Diffstat (limited to 'experiments/plot_contrastive_bias_b1.py')
| -rw-r--r-- | experiments/plot_contrastive_bias_b1.py | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/experiments/plot_contrastive_bias_b1.py b/experiments/plot_contrastive_bias_b1.py new file mode 100644 index 0000000..5fc70d1 --- /dev/null +++ b/experiments/plot_contrastive_bias_b1.py @@ -0,0 +1,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() |
