#!/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()