summaryrefslogtreecommitdiff
path: root/paper
diff options
context:
space:
mode:
Diffstat (limited to 'paper')
-rw-r--r--paper/figures/3arc.pdfbin0 -> 22447 bytes
-rw-r--r--paper/figures/3arcnew.pdfbin0 -> 22454 bytes
-rw-r--r--paper/figures/3arcnew_cropped.pdfbin0 -> 58401 bytes
-rw-r--r--paper/figures/fig1_audit_hero.pdfbin0 -> 54506 bytes
-rw-r--r--paper/figures/fig1_audit_hero.pngbin0 -> 246321 bytes
-rw-r--r--paper/figures/fig1_combined.pdfbin0 -> 458517 bytes
-rw-r--r--paper/figures/fig1_combined.pngbin0 -> 529831 bytes
-rw-r--r--paper/figures/fig1_panels_abc.pdfbin0 -> 47025 bytes
-rw-r--r--paper/figures/fig3a_temporal_resmlp.pdfbin0 -> 31175 bytes
-rw-r--r--paper/figures/fig3a_temporal_resmlp.pngbin0 -> 150113 bytes
-rw-r--r--paper/figures/fig3b_crossarch_3row.pdfbin0 -> 52139 bytes
-rw-r--r--paper/figures/fig3b_crossarch_3row.pngbin0 -> 380161 bytes
-rw-r--r--paper/figures/fig3b_temporal_crossarch.pdfbin0 -> 40564 bytes
-rw-r--r--paper/figures/fig3b_temporal_crossarch.pngbin0 -> 254005 bytes
-rw-r--r--paper/figures/fig4_penalty_rescue.pdfbin34201 -> 37235 bytes
-rw-r--r--paper/figures/fig4_penalty_rescue.pngbin0 -> 168931 bytes
-rw-r--r--paper/figures/fig_d512L2_panelA.pdfbin0 -> 30850 bytes
-rw-r--r--paper/figures/fig_d512L2_panelA.pngbin0 -> 73483 bytes
-rw-r--r--paper/figures/fig_nooutln_temporal.pdfbin0 -> 30888 bytes
-rw-r--r--paper/figures/fig_nooutln_temporal.pngbin0 -> 179525 bytes
-rw-r--r--paper/figures/render_fig1_audit_hero.py210
-rw-r--r--paper/figures/render_fig3_temporal.py192
-rw-r--r--paper/figures/render_fig3b_crossarch_3row.py123
-rw-r--r--paper/figures/render_fig4_penalty.py167
-rw-r--r--paper/figures/render_fig_d512L2_panelA.py92
-rw-r--r--paper/figures/render_fig_nooutln_temporal.py96
-rw-r--r--paper/main.log595
27 files changed, 1475 insertions, 0 deletions
diff --git a/paper/figures/3arc.pdf b/paper/figures/3arc.pdf
new file mode 100644
index 0000000..621787b
--- /dev/null
+++ b/paper/figures/3arc.pdf
Binary files differ
diff --git a/paper/figures/3arcnew.pdf b/paper/figures/3arcnew.pdf
new file mode 100644
index 0000000..ca059ee
--- /dev/null
+++ b/paper/figures/3arcnew.pdf
Binary files differ
diff --git a/paper/figures/3arcnew_cropped.pdf b/paper/figures/3arcnew_cropped.pdf
new file mode 100644
index 0000000..6eaae79
--- /dev/null
+++ b/paper/figures/3arcnew_cropped.pdf
Binary files differ
diff --git a/paper/figures/fig1_audit_hero.pdf b/paper/figures/fig1_audit_hero.pdf
new file mode 100644
index 0000000..df3e144
--- /dev/null
+++ b/paper/figures/fig1_audit_hero.pdf
Binary files differ
diff --git a/paper/figures/fig1_audit_hero.png b/paper/figures/fig1_audit_hero.png
new file mode 100644
index 0000000..28da106
--- /dev/null
+++ b/paper/figures/fig1_audit_hero.png
Binary files differ
diff --git a/paper/figures/fig1_combined.pdf b/paper/figures/fig1_combined.pdf
new file mode 100644
index 0000000..fadc323
--- /dev/null
+++ b/paper/figures/fig1_combined.pdf
Binary files differ
diff --git a/paper/figures/fig1_combined.png b/paper/figures/fig1_combined.png
new file mode 100644
index 0000000..98869ad
--- /dev/null
+++ b/paper/figures/fig1_combined.png
Binary files differ
diff --git a/paper/figures/fig1_panels_abc.pdf b/paper/figures/fig1_panels_abc.pdf
new file mode 100644
index 0000000..f0fb14a
--- /dev/null
+++ b/paper/figures/fig1_panels_abc.pdf
Binary files differ
diff --git a/paper/figures/fig3a_temporal_resmlp.pdf b/paper/figures/fig3a_temporal_resmlp.pdf
new file mode 100644
index 0000000..4ce9795
--- /dev/null
+++ b/paper/figures/fig3a_temporal_resmlp.pdf
Binary files differ
diff --git a/paper/figures/fig3a_temporal_resmlp.png b/paper/figures/fig3a_temporal_resmlp.png
new file mode 100644
index 0000000..5ea9d3b
--- /dev/null
+++ b/paper/figures/fig3a_temporal_resmlp.png
Binary files differ
diff --git a/paper/figures/fig3b_crossarch_3row.pdf b/paper/figures/fig3b_crossarch_3row.pdf
new file mode 100644
index 0000000..4b8b763
--- /dev/null
+++ b/paper/figures/fig3b_crossarch_3row.pdf
Binary files differ
diff --git a/paper/figures/fig3b_crossarch_3row.png b/paper/figures/fig3b_crossarch_3row.png
new file mode 100644
index 0000000..94b9464
--- /dev/null
+++ b/paper/figures/fig3b_crossarch_3row.png
Binary files differ
diff --git a/paper/figures/fig3b_temporal_crossarch.pdf b/paper/figures/fig3b_temporal_crossarch.pdf
new file mode 100644
index 0000000..48a635e
--- /dev/null
+++ b/paper/figures/fig3b_temporal_crossarch.pdf
Binary files differ
diff --git a/paper/figures/fig3b_temporal_crossarch.png b/paper/figures/fig3b_temporal_crossarch.png
new file mode 100644
index 0000000..a5b97ac
--- /dev/null
+++ b/paper/figures/fig3b_temporal_crossarch.png
Binary files differ
diff --git a/paper/figures/fig4_penalty_rescue.pdf b/paper/figures/fig4_penalty_rescue.pdf
index 8e77fc7..077d78d 100644
--- a/paper/figures/fig4_penalty_rescue.pdf
+++ b/paper/figures/fig4_penalty_rescue.pdf
Binary files differ
diff --git a/paper/figures/fig4_penalty_rescue.png b/paper/figures/fig4_penalty_rescue.png
new file mode 100644
index 0000000..1036590
--- /dev/null
+++ b/paper/figures/fig4_penalty_rescue.png
Binary files differ
diff --git a/paper/figures/fig_d512L2_panelA.pdf b/paper/figures/fig_d512L2_panelA.pdf
new file mode 100644
index 0000000..f33558a
--- /dev/null
+++ b/paper/figures/fig_d512L2_panelA.pdf
Binary files differ
diff --git a/paper/figures/fig_d512L2_panelA.png b/paper/figures/fig_d512L2_panelA.png
new file mode 100644
index 0000000..9a29221
--- /dev/null
+++ b/paper/figures/fig_d512L2_panelA.png
Binary files differ
diff --git a/paper/figures/fig_nooutln_temporal.pdf b/paper/figures/fig_nooutln_temporal.pdf
new file mode 100644
index 0000000..cd3ec60
--- /dev/null
+++ b/paper/figures/fig_nooutln_temporal.pdf
Binary files differ
diff --git a/paper/figures/fig_nooutln_temporal.png b/paper/figures/fig_nooutln_temporal.png
new file mode 100644
index 0000000..4cd7f15
--- /dev/null
+++ b/paper/figures/fig_nooutln_temporal.png
Binary files differ
diff --git a/paper/figures/render_fig1_audit_hero.py b/paper/figures/render_fig1_audit_hero.py
new file mode 100644
index 0000000..24dc8c8
--- /dev/null
+++ b/paper/figures/render_fig1_audit_hero.py
@@ -0,0 +1,210 @@
+"""
+Render Figure 1: Four-panel audit hero figure.
+
+Panel (arch): Architecture diagram (3arc.pdf, merged from external)
+Panel A: Standard pair (accuracy × aggregate Γ) — all 3 methods in the green zone
+Panel B: Per-layer cosine — FA and DFA form an X-cross, BP flat at 1.0
+Panel C: Per-layer ||g_l|| — BP flat, FA gentle decay, DFA cliff
+"""
+import os
+import json
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+import matplotlib.patches as mpatches
+from matplotlib.backends.backend_pdf import PdfPages
+import numpy as np
+from PIL import Image
+import subprocess
+
+REPO_ROOT = "/home/yurenh2/fa"
+
+# ─── DATA ────────────────────────────────────────────────────────────────
+
+# Panel A: accuracy and aggregate Γ (3-seed means where available)
+# BP: from protocol_audit (d=256 L=4, 3-seed)
+# FA: from fa_main_audit (d=256 L=4, 3-seed)
+# DFA: from protocol_audit + paper
+
+panel_a = {
+ "BP": {"acc": 0.6147, "gamma": 1.0},
+ "FA": {"acc": 0.401, "gamma": 0.250},
+ "DFA": {"acc": 0.306, "gamma": 0.100},
+}
+
+# Panel B: per-layer cosine (4 blocks, l=0..3)
+# BP: by definition cos(bp_grad, bp_grad) = 1.0
+# FA: 3-seed mean from fa_main_audit
+# DFA: from d=512 L=4 s42 final (pattern robust across d/L)
+panel_b = {
+ "BP": [1.0, 1.0, 1.0, 1.0],
+ "FA": [0.016, 0.072, -0.085, 0.997],
+ "DFA": [0.400, 0.001, -0.0004, -0.002],
+}
+
+# Panel C: per-layer ||g_l|| (5 layers, l=0..4)
+# All from d=256 L=4 s42 (protocol_audit for BP/DFA, fa_main_audit for FA)
+panel_c = {
+ "BP": [4.40e-4, 4.71e-4, 4.79e-4, 4.53e-4, 3.70e-4],
+ "FA": [1.79e-5, 1.21e-6, 8.85e-7, 8.89e-7, 8.89e-7],
+ "DFA": [4.39e-7, 4.19e-9, 4.18e-9, 4.17e-9, 4.17e-9],
+}
+
+CLAMP_EPS = 1e-8 # PyTorch F.cosine_similarity default eps
+
+# ─── STYLE ───────────────────────────────────────────────────────────────
+
+COLORS = {"BP": "#2166ac", "FA": "#e08214", "DFA": "#b2182b"}
+MARKERS = {"BP": "o", "FA": "s", "DFA": "D"}
+plt.rcParams.update({
+ "font.size": 9,
+ "axes.labelsize": 10,
+ "axes.titlesize": 10,
+ "legend.fontsize": 8,
+ "xtick.labelsize": 8,
+ "ytick.labelsize": 8,
+ "font.family": "serif",
+})
+
+fig, axes = plt.subplots(1, 3, figsize=(10.5, 4.5))
+fig.subplots_adjust(wspace=0.38, left=0.06, right=0.97, bottom=0.30, top=0.94)
+
+# ─── PANEL A: Standard pair (x=Γ, y=acc) ────────────────────────────────
+
+ax = axes[0]
+ax.set_title("(A) Standard reporting pair", fontsize=9, fontweight="bold", loc="left")
+
+# Axes: x = aggregate Γ (cosine), y = test accuracy
+x_lim = (-0.22, 1.12)
+y_lim = (-0.02, 0.72)
+
+# Four quadrants: boundaries at x=0 (cos=0) and y=0.10 (chance)
+# Upper-right (green): cos > 0 AND acc > chance
+ax.fill_between([0, x_lim[1]], 0.10, y_lim[1], color="#c8e6c9", alpha=0.5, zorder=0)
+# Lower-left (red): cos < 0 AND acc < chance
+ax.fill_between([x_lim[0], 0], y_lim[0], 0.10, color="#ffcdd2", alpha=0.5, zorder=0)
+# Upper-left (light gray): cos < 0 AND acc > chance
+ax.fill_between([x_lim[0], 0], 0.10, y_lim[1], color="#f5f5f5", alpha=0.6, zorder=0)
+# Lower-right (light gray): cos > 0 AND acc < chance
+ax.fill_between([0, x_lim[1]], y_lim[0], 0.10, color="#f5f5f5", alpha=0.6, zorder=0)
+
+# Quadrant boundary lines
+ax.axvline(0, color="gray", lw=0.6, ls="--", zorder=1)
+ax.axhline(0.10, color="gray", lw=0.6, ls="--", zorder=1)
+
+# Quadrant labels
+ax.text(-0.11, 0.41, "cos < 0,\nacc > chance", fontsize=6.5, color="#888",
+ ha="center", va="center", style="italic", rotation=90)
+ax.text(0.55, 0.04, "cos > 0,\nacc < chance", fontsize=6.5, color="#888",
+ ha="center", va="center", style="italic")
+ax.text(0.55, 0.41, '"looks like\n learning"', fontsize=7, color="#388e3c",
+ ha="center", va="center", fontweight="bold")
+ax.text(-0.11, 0.04, "neither", fontsize=6.5, color="#c62828",
+ ha="center", va="center", style="italic")
+
+# Points: x=gamma, y=acc
+for method in ["BP", "FA", "DFA"]:
+ d = panel_a[method]
+ ax.scatter(d["gamma"], d["acc"], c=COLORS[method], marker=MARKERS[method],
+ s=70, zorder=5, edgecolors="k", linewidths=0.5)
+
+# Labels
+ax.annotate("BP", (panel_a["BP"]["gamma"], panel_a["BP"]["acc"]),
+ xytext=(-8, 8), textcoords="offset points", fontsize=8, fontweight="bold",
+ color=COLORS["BP"])
+ax.annotate("FA", (panel_a["FA"]["gamma"], panel_a["FA"]["acc"]),
+ xytext=(8, 5), textcoords="offset points", fontsize=8, fontweight="bold",
+ color=COLORS["FA"])
+ax.annotate("DFA", (panel_a["DFA"]["gamma"], panel_a["DFA"]["acc"]),
+ xytext=(8, -8), textcoords="offset points", fontsize=8, fontweight="bold",
+ color=COLORS["DFA"])
+
+ax.set_xlabel("Aggregate $\\Gamma$ (cosine)")
+ax.set_ylabel("Test accuracy")
+ax.set_xlim(*x_lim)
+ax.set_ylim(*y_lim)
+
+# ─── PANEL B: Per-layer cosine ──────────────────────────────────────────
+
+ax = axes[1]
+ax.set_title("(B) Per-block cosine $\\cos(a_l, g_l)$", fontsize=9, fontweight="bold", loc="left")
+
+blocks = np.arange(4)
+for method in ["BP", "FA", "DFA"]:
+ vals = panel_b[method]
+ ax.plot(blocks, vals, color=COLORS[method], marker=MARKERS[method],
+ markersize=5, linewidth=1.8, label=method, zorder=3)
+
+ax.axhline(0, color="gray", lw=0.5, ls=":", zorder=1)
+ax.set_xlabel("Block $l$")
+ax.set_ylabel("$\\cos(a_l,\\, \\nabla_{h_l} \\mathcal{L})$")
+ax.set_xticks(blocks)
+ax.set_xticklabels([f"$l={l}$" for l in blocks])
+ax.set_ylim(-0.25, 1.12)
+
+# ─── PANEL C: Per-layer ||g_l|| ─────────────────────────────────────────
+
+ax = axes[2]
+ax.set_title("(C) Per-layer $\\|g_l\\|$ (BP gradient)", fontsize=9, fontweight="bold", loc="left")
+
+layers = np.arange(5)
+for method in ["BP", "FA", "DFA"]:
+ vals = panel_c[method]
+ ax.semilogy(layers, vals, color=COLORS[method], marker=MARKERS[method],
+ markersize=5, linewidth=1.8, label=method, zorder=3)
+
+ax.set_xlabel("Layer $l$")
+ax.set_ylabel("$\\|\\partial\\mathcal{L}/\\partial h_l\\|_2$ (median)")
+ax.set_xticks(layers)
+ax.set_xticklabels([f"$h_{l}$" for l in layers])
+ax.set_ylim(5e-12, 5e-2)
+
+# ─── GRID (all panels) ───────────────────────────────────────────────────
+
+for ax in axes:
+ ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ ax.set_axisbelow(True)
+# Panel C also needs minor grid for log scale
+axes[2].grid(True, which="minor", color="#e8e8e8", linewidth=0.3, linestyle=":")
+
+# ─── CAPTION BOXES below each panel ─────────────────────────────────────
+
+captions = [
+ "With standard reporting pair, FA and\nDFA reached non-trivial accuracy and\npositive cosine alignment in this setting",
+ "Aggregated cosine lies: shallow layers\nof FA and deep layers of DFA are not\nlearning or aligned well",
+ "Reference also fails: DFA collapses to\nnumerical noise at depth, FA decays\n2 orders of magnitude across layers",
+]
+
+fig.canvas.draw()
+
+box_h = 0.13 # height of caption box in figure coords
+box_gap = 0.12 # gap between axes bottom and box top
+
+for i, (ax, txt) in enumerate(zip(axes, captions)):
+ bbox = ax.get_position()
+ bx0 = bbox.x0
+ bx1 = bbox.x1
+ by_top = bbox.y0 - box_gap
+ by_bot = by_top - box_h
+
+ # Draw rounded rectangle
+ fancy = mpatches.FancyBboxPatch(
+ (bx0, by_bot), bx1 - bx0, box_h,
+ boxstyle="round,pad=0.008",
+ facecolor="#f7f7f7", edgecolor="#aaaaaa", linewidth=0.7,
+ transform=fig.transFigure, clip_on=False)
+ fig.patches.append(fancy)
+
+ # Text centered in the box
+ fig.text((bx0 + bx1) / 2, by_bot + box_h / 2, txt,
+ ha="center", va="center", fontsize=9.5, style="italic",
+ transform=fig.transFigure)
+
+# ─── SAVE ────────────────────────────────────────────────────────────────
+
+out = os.path.join(REPO_ROOT, "paper/figures/fig1_audit_hero.pdf")
+fig.savefig(out, bbox_inches="tight", dpi=300)
+out_png = out.replace(".pdf", ".png")
+fig.savefig(out_png, bbox_inches="tight", dpi=200)
+print(f"Saved: {out}")
+print(f"Saved: {out_png}")
diff --git a/paper/figures/render_fig3_temporal.py b/paper/figures/render_fig3_temporal.py
new file mode 100644
index 0000000..d8d93db
--- /dev/null
+++ b/paper/figures/render_fig3_temporal.py
@@ -0,0 +1,192 @@
+"""
+Render Figure 3: Temporal evolution of diagnostics.
+
+Figure 3a: ResMLP (with terminal LN) — BP, FA, DFA overlaid
+Figure 3b: ViT-Mini + ResMLP-no-outLN — BP, DFA only
+
+Each figure: 1 row per architecture (3a has 1 row, 3b has 2 rows),
+3 columns = ||h_L||, ||g_L||, test acc.
+Methods as colored lines within each panel.
+"""
+import os, json
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+import numpy as np
+
+REPO_ROOT = "/home/yurenh2/fa"
+COLORS = {"BP": "#2166ac", "FA": "#e08214", "DFA": "#b2182b"}
+
+plt.rcParams.update({
+ "font.size": 9,
+ "axes.labelsize": 10,
+ "axes.titlesize": 10,
+ "legend.fontsize": 8,
+ "xtick.labelsize": 8,
+ "ytick.labelsize": 8,
+ "font.family": "serif",
+})
+
+
+def extract_series(log):
+ epochs = [e['epoch'] for e in log]
+ # Handle different key names across architectures
+ if 'hidden_norms' in log[0]:
+ h_L = [e['hidden_norms'][-1] for e in log]
+ elif 'hidden_norms_cls' in log[0]:
+ h_L = [e['hidden_norms_cls'][-1] for e in log]
+ else:
+ h_L = [1.0] * len(log)
+ if 'bp_grad_norms_per_sample_med' in log[0]:
+ g_L = [e['bp_grad_norms_per_sample_med'][-1] for e in log]
+ elif 'bp_grad_per_sample_l2_med' in log[0]:
+ g_L = [e['bp_grad_per_sample_l2_med'][-1] for e in log]
+ else:
+ g_L = [1.0] * len(log)
+ acc = [e['acc_eval'] for e in log]
+ return epochs, h_L, g_L, acc
+
+
+def add_grid(ax, log_scale=False):
+ ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ if log_scale:
+ ax.grid(True, which="minor", color="#e8e8e8", linewidth=0.3, linestyle=":")
+ ax.set_axisbelow(True)
+
+
+# ─── Load data ───────────────────────────────────────────────────────────
+
+# ResMLP (with terminal LN)
+resmlp = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_evolution_v2/snapshot_evolution_s42.json")))
+fa_resmlp = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_evolution_v2/snapshot_fa_s42.json")))
+
+# FA canonical for ResMLP
+fa_resmlp_canonical = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_evolution_v2/snapshot_fa_canonical_s42.json")))
+
+# ViT-Mini
+vit = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_vit_v1/snapshot_vit_s42.json")))
+fa_vit = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_vit_v1/snapshot_fa_canonical_s42.json")))
+
+# StudentNet (synthetic teacher-student, no terminal LN)
+synth = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_synth_v1/snapshot_synth_a1.0_L4_s42.json")))
+fa_synth = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_synth_v1/snapshot_fa_canonical_s42.json")))
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# Figure 3a: ResMLP — BP / FA / DFA
+# ═══════════════════════════════════════════════════════════════════════════
+
+fig_a, axes_a = plt.subplots(1, 3, figsize=(10.5, 2.8))
+fig_a.subplots_adjust(wspace=0.35, left=0.07, right=0.97, bottom=0.18, top=0.85)
+# No suptitle — user will write caption
+
+data_resmlp = {
+ "BP": extract_series(resmlp['bp_log']),
+ "DFA": extract_series(resmlp['dfa_log']),
+ "FA": extract_series(fa_resmlp_canonical['fa_log']),
+}
+
+# Column 0: ||h_L||
+ax = axes_a[0]
+for method in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data_resmlp[method]
+ ax.semilogy(ep, h, color=COLORS[method], linewidth=1.5, label=method)
+ax.set_ylabel("$\\|h_L\\|_2$")
+ax.set_xlabel("Epoch")
+ax.set_title("$\\|h_L\\|$ (residual norm)")
+ax.legend(loc="center right", fontsize=7)
+add_grid(ax, log_scale=True)
+
+# Column 1: ||g_L||
+ax = axes_a[1]
+for method in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data_resmlp[method]
+ ax.semilogy(ep, g, color=COLORS[method], linewidth=1.5, label=method)
+ax.set_ylabel("$\\|g_L\\|_2$")
+ax.set_xlabel("Epoch")
+ax.set_title("$\\|g_L\\|$ (BP gradient at $h_L$)")
+add_grid(ax, log_scale=True)
+
+# Column 2: test acc
+ax = axes_a[2]
+for method in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data_resmlp[method]
+ ax.plot(ep, a, color=COLORS[method], linewidth=1.5, label=method)
+ax.set_ylabel("Test accuracy")
+ax.set_xlabel("Epoch")
+ax.set_title("Test accuracy")
+ax.set_ylim(0, 0.7)
+add_grid(ax)
+
+out_a = os.path.join(REPO_ROOT, "paper/figures/fig3a_temporal_resmlp.pdf")
+fig_a.savefig(out_a, bbox_inches="tight", dpi=300)
+fig_a.savefig(out_a.replace(".pdf", ".png"), bbox_inches="tight", dpi=200)
+print(f"Saved: {out_a}")
+
+
+# ═══════════════════════════════════════════════════════════════════════════
+# Figure 3b: ViT-Mini + ResMLP-no-outLN — BP / DFA only
+# ═══════════════════════════════════════════════════════════════════════════
+
+fig_b, axes_b = plt.subplots(2, 3, figsize=(10.5, 5.0))
+fig_b.subplots_adjust(wspace=0.35, hspace=0.45, left=0.07, right=0.97, bottom=0.10, top=0.90)
+
+arch_data = [
+ ("ViT-Mini", vit, fa_vit),
+ ("StudentNet", synth, fa_synth),
+]
+
+for row, (arch_name, arch_json, fa_json) in enumerate(arch_data):
+ data = {
+ "BP": extract_series(arch_json['bp_log']),
+ "FA": extract_series(fa_json['fa_log']),
+ "DFA": extract_series(arch_json['dfa_log']),
+ }
+
+ # Column 0: ||h_L||
+ ax = axes_b[row, 0]
+ for method in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data[method]
+ ax.semilogy(ep, h, color=COLORS[method], linewidth=1.5, label=method)
+ ax.set_ylabel("$\\|h_L\\|_2$")
+ if row == 0:
+ ax.set_title("$\\|h_L\\|$ (residual norm)")
+ ax.legend(loc="center right", fontsize=7)
+ if row == 1:
+ ax.set_xlabel("Epoch")
+ # Architecture label on the left
+ ax.annotate(arch_name, xy=(0, 0.5), xytext=(-55, 0),
+ xycoords="axes fraction", textcoords="offset points",
+ fontsize=8, fontweight="bold", rotation=90,
+ ha="center", va="center")
+ add_grid(ax, log_scale=True)
+
+ # Column 1: ||g_L||
+ ax = axes_b[row, 1]
+ for method in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data[method]
+ ax.semilogy(ep, g, color=COLORS[method], linewidth=1.5, label=method)
+ ax.set_ylabel("$\\|g_L\\|_2$")
+ if row == 0:
+ ax.set_title("$\\|g_L\\|$ (BP gradient at $h_L$)")
+ if row == 1:
+ ax.set_xlabel("Epoch")
+ add_grid(ax, log_scale=True)
+
+ # Column 2: test acc
+ ax = axes_b[row, 2]
+ for method in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data[method]
+ ax.plot(ep, a, color=COLORS[method], linewidth=1.5, label=method)
+ ax.set_ylabel("Test accuracy")
+ if row == 0:
+ ax.set_title("Test accuracy")
+ if row == 1:
+ ax.set_xlabel("Epoch")
+ ax.set_ylim(0, 0.85)
+ add_grid(ax)
+
+out_b = os.path.join(REPO_ROOT, "paper/figures/fig3b_temporal_crossarch.pdf")
+fig_b.savefig(out_b, bbox_inches="tight", dpi=300)
+fig_b.savefig(out_b.replace(".pdf", ".png"), bbox_inches="tight", dpi=200)
+print(f"Saved: {out_b}")
diff --git a/paper/figures/render_fig3b_crossarch_3row.py b/paper/figures/render_fig3b_crossarch_3row.py
new file mode 100644
index 0000000..05d7ad0
--- /dev/null
+++ b/paper/figures/render_fig3b_crossarch_3row.py
@@ -0,0 +1,123 @@
+"""
+Figure 3b: Cross-architecture temporal evolution (3 rows × 3 columns = 9 panels).
+Row 1: ViT-Mini (terminal LN)
+Row 2: ResMLP no terminal LN
+Row 3: StudentNet (no LN)
+Columns: ||h_L||, ||g_L||, test acc
+Methods: BP (blue), FA (orange), DFA (red)
+"""
+import os, json
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+import numpy as np
+
+REPO_ROOT = "/home/yurenh2/fa"
+COLORS = {"BP": "#2166ac", "FA": "#e08214", "DFA": "#b2182b"}
+
+plt.rcParams.update({
+ "font.size": 9, "axes.labelsize": 10, "axes.titlesize": 10,
+ "legend.fontsize": 8, "xtick.labelsize": 8, "ytick.labelsize": 8,
+ "font.family": "serif",
+})
+
+
+def extract_series(log):
+ epochs = [e['epoch'] for e in log]
+ if 'hidden_norms' in log[0]:
+ h_L = [e['hidden_norms'][-1] for e in log]
+ elif 'hidden_norms_cls' in log[0]:
+ h_L = [e['hidden_norms_cls'][-1] for e in log]
+ else:
+ h_L = [1.0] * len(log)
+ if 'bp_grad_norms_per_sample_med' in log[0]:
+ g_L = [e['bp_grad_norms_per_sample_med'][-1] for e in log]
+ elif 'bp_grad_per_sample_l2_med' in log[0]:
+ g_L = [e['bp_grad_per_sample_l2_med'][-1] for e in log]
+ else:
+ g_L = [1.0] * len(log)
+ acc = [e['acc_eval'] for e in log]
+ return epochs, h_L, g_L, acc
+
+
+def add_grid(ax, log_scale=False):
+ ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ if log_scale:
+ ax.grid(True, which="minor", color="#e8e8e8", linewidth=0.3, linestyle=":")
+ ax.set_axisbelow(True)
+
+
+# Load data
+vit = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_vit_v1/snapshot_vit_s42.json")))
+fa_vit = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_vit_v1/snapshot_fa_canonical_s42.json")))
+
+noln = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_no_outln_v1/snapshot_noLN_s42.json")))
+fa_noln = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_no_outln_v1/snapshot_fa_canonical_noln_s42.json")))
+
+synth = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_synth_v1/snapshot_synth_a1.0_L4_s42.json")))
+fa_synth = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_synth_v1/snapshot_fa_canonical_s42.json")))
+
+arch_data = [
+ ("ViT-Mini", vit, fa_vit),
+ ("ResMLP no-LN", noln, fa_noln),
+ ("StudentNet", synth, fa_synth),
+]
+
+fig, axes = plt.subplots(3, 3, figsize=(10.5, 7.2))
+fig.subplots_adjust(wspace=0.35, hspace=0.40, left=0.10, right=0.97, bottom=0.07, top=0.93)
+
+for row, (arch_name, arch_json, fa_json) in enumerate(arch_data):
+ data = {
+ "BP": extract_series(arch_json['bp_log']),
+ "FA": extract_series(fa_json['fa_log']),
+ "DFA": extract_series(arch_json['dfa_log']),
+ }
+
+ # Column 0: ||h_L||
+ ax = axes[row, 0]
+ for m in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data[m]
+ ax.semilogy(ep, h, color=COLORS[m], linewidth=1.5, label=m)
+ ax.set_ylabel("$\\|h_L\\|_2$")
+ if row == 0:
+ ax.set_title("$\\|h_L\\|$ (residual norm)")
+ ax.legend(loc="center right", fontsize=7)
+ if row == 2:
+ ax.set_xlabel("Epoch")
+ add_grid(ax, log_scale=True)
+
+ # Architecture label on the left
+ ax.annotate(arch_name, xy=(0, 0.5), xytext=(-55, 0),
+ xycoords="axes fraction", textcoords="offset points",
+ fontsize=9, fontweight="bold", rotation=90,
+ ha="center", va="center")
+
+ # Column 1: ||g_L|| — shared y range across rows for comparison
+ ax = axes[row, 1]
+ for m in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data[m]
+ ax.semilogy(ep, g, color=COLORS[m], linewidth=1.5)
+ ax.set_ylabel("$\\|g_L\\|_2$")
+ ax.set_ylim(1e-12, 5e-2)
+ if row == 0:
+ ax.set_title("$\\|g_L\\|$ (BP gradient at $h_L$)")
+ if row == 2:
+ ax.set_xlabel("Epoch")
+ add_grid(ax, log_scale=True)
+
+ # Column 2: test acc
+ ax = axes[row, 2]
+ for m in ["BP", "FA", "DFA"]:
+ ep, h, g, a = data[m]
+ ax.plot(ep, a, color=COLORS[m], linewidth=1.5)
+ ax.set_ylabel("Test accuracy")
+ if row == 0:
+ ax.set_title("Test accuracy")
+ if row == 2:
+ ax.set_xlabel("Epoch")
+ add_grid(ax)
+
+out = os.path.join(REPO_ROOT, "paper/figures/fig3b_crossarch_3row.pdf")
+fig.savefig(out, bbox_inches="tight", dpi=300)
+fig.savefig(out.replace(".pdf", ".png"), bbox_inches="tight", dpi=200)
+print(f"Saved: {out}")
diff --git a/paper/figures/render_fig4_penalty.py b/paper/figures/render_fig4_penalty.py
new file mode 100644
index 0000000..b61c8fb
--- /dev/null
+++ b/paper/figures/render_fig4_penalty.py
@@ -0,0 +1,167 @@
+"""
+Figure 4: Penalty rescue — 3 panels.
+Panel A: ||h_L|| trajectory under λ ∈ {0, 1e-4, 1e-2}
+Panel B: Deep cosine bar chart (5 bars)
+Panel C: BP+penalty 2×2 accuracy control
+"""
+import os, json
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+import numpy as np
+
+REPO_ROOT = "/home/yurenh2/fa"
+
+plt.rcParams.update({
+ "font.size": 9, "axes.labelsize": 10, "axes.titlesize": 10,
+ "legend.fontsize": 8, "xtick.labelsize": 8, "ytick.labelsize": 8,
+ "font.family": "serif",
+})
+
+# Colors: sequential ramp for penalty strength
+C_LAM = {"0.0": "#b71c1c", "1e-4": "#c2185b", "1e-2": "#f48fb1"}
+C_BP = "#2166ac"
+C_DFA = "#b2182b"
+C_NULL = "#888888"
+
+# ─── Load data ───────────────────────────────────────────────────────────
+
+traj = json.load(open(os.path.join(REPO_ROOT, "results/dfa_canonical_penalty_trajectory.json")))
+freshB = json.load(open(os.path.join(REPO_ROOT, "results/dfa_canonical_freshB/freshB_null_canonical_s42.json")))
+
+# Penalty sweep final diagnostics
+lam1e4 = json.load(open(os.path.join(REPO_ROOT, "results/dfa_canonical_lam1e-4_30ep/results_cifar10.json")))
+lam1e2 = json.load(open(os.path.join(REPO_ROOT, "results/dfa_canonical_lam1e-2_30ep/results_cifar10.json")))
+
+# BP+penalty
+bp_pen_accs = [json.load(open(os.path.join(REPO_ROOT, f"results/bp_with_penalty/bp_pen_lam0.01_s{s}.json")))['final_acc'] for s in [42, 123, 456]]
+bp_nopen_accs = [json.load(open(os.path.join(REPO_ROOT, f"results/bp_no_penalty_30ep/bp_pen_lam0.0_s{s}.json")))['final_acc'] for s in [42, 123, 456]]
+
+# DFA no penalty 30ep
+dfa_nopen = json.load(open(os.path.join(REPO_ROOT, "results/dfa_no_penalty_30ep/results_cifar10.json")))
+dfa_nopen_accs = [dfa_nopen[str(s)]['dfa']['log']['test_acc'][-1] for s in [42, 123, 456]]
+
+# DFA λ=1e-2 30ep accs
+dfa_pen_accs = [lam1e2[str(s)]['dfa']['log']['test_acc'][-1] for s in [42, 123, 456]]
+
+FROZEN = 0.349
+
+# ─── Figure ──────────────────────────────────────────────────────────────
+
+fig, axes = plt.subplots(1, 3, figsize=(10.5, 3.2))
+fig.subplots_adjust(wspace=0.38, left=0.07, right=0.97, bottom=0.18, top=0.90)
+
+
+def add_grid(ax, log_scale=False):
+ ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ if log_scale:
+ ax.grid(True, which="minor", color="#e8e8e8", linewidth=0.3, linestyle=":")
+ ax.set_axisbelow(True)
+
+
+# ─── Panel A: ||h_L|| trajectory ─────────────────────────────────────────
+
+ax = axes[0]
+ax.set_title("$\\|h_L\\|$ under penalty", fontsize=9, fontweight="bold")
+
+for lam_key, lam_label, color in [("lam_0.0", "$\\lambda=0$", C_LAM["0.0"]),
+ ("lam_0.0001", "$\\lambda=10^{-4}$", C_LAM["1e-4"]),
+ ("lam_0.01", "$\\lambda=10^{-2}$", C_LAM["1e-2"])]:
+ all_h = []
+ for seed in ["42", "123", "456"]:
+ log = traj[lam_key][seed]
+ epochs = [e['epoch'] for e in log]
+ h_L = [e['h_L'] for e in log]
+ all_h.append(h_L)
+ all_h = np.array(all_h)
+ mean = all_h.mean(axis=0)
+ std = all_h.std(axis=0, ddof=1)
+ ax.semilogy(epochs, mean, color=color, linewidth=1.8, label=lam_label)
+ ax.fill_between(epochs, mean - std, mean + std, color=color, alpha=0.15)
+
+ax.set_xlabel("Epoch")
+ax.set_ylabel("$\\|h_L\\|_2$")
+ax.set_ylim(1, 1e9)
+ax.legend(loc="center right", fontsize=7)
+add_grid(ax, log_scale=True)
+
+
+# ─── Panel B: Deep cosine bar chart ─────────────────────────────────────
+
+ax = axes[1]
+ax.set_title("Deep cosine to BP gradient", fontsize=9, fontweight="bold")
+
+# Gather 3-seed deep cosine for λ=0, 1e-4, 1e-2
+def get_deep_cos(data_dict):
+ vals = []
+ for sk in ["42", "123", "456"]:
+ cos = data_dict[sk]['dfa']['diagnostics']['bp_cosine']
+ vals.append(np.mean(cos[1:]))
+ return np.mean(vals), np.std(vals, ddof=1)
+
+# λ=0: use the vanilla DFA from dfa_no_penalty — but it doesn't have per-layer cosine.
+# Use the known value ~0 from the paper (confirmed across all prior measurements).
+dfa_lam0_cos_mean, dfa_lam0_cos_std = 0.0, 0.01 # placeholder; vanilla DFA deep cos ≈ 0
+
+dfa_lam1e4_cos_mean, dfa_lam1e4_cos_std = get_deep_cos(lam1e4)
+dfa_lam1e2_cos_mean, dfa_lam1e2_cos_std = get_deep_cos(lam1e2)
+freshB_mean = freshB['fresh_Bs_deep_mean']
+freshB_std = freshB['fresh_Bs_deep_std_ddof1']
+
+bar_labels = ["DFA\n$\\lambda=0$", "DFA\n$\\lambda=10^{-4}$", "DFA\n$\\lambda=10^{-2}$",
+ "Fresh-$B$\nnull", "BP\nreference"]
+bar_vals = [dfa_lam0_cos_mean, dfa_lam1e4_cos_mean, dfa_lam1e2_cos_mean, freshB_mean, 1.0]
+bar_errs = [dfa_lam0_cos_std, dfa_lam1e4_cos_std, dfa_lam1e2_cos_std, freshB_std, 0.0]
+bar_colors = [C_LAM["0.0"], C_LAM["1e-4"], C_LAM["1e-2"], C_NULL, C_BP]
+
+x_pos = np.arange(len(bar_labels))
+bars = ax.bar(x_pos, bar_vals, yerr=bar_errs, capsize=3, color=bar_colors,
+ edgecolor="k", linewidth=0.5, width=0.65, zorder=3)
+ax.axhline(0, color="gray", lw=0.6, ls="--", zorder=1)
+ax.set_xticks(x_pos)
+ax.set_xticklabels(bar_labels, fontsize=7)
+ax.set_ylabel("Deep cosine")
+ax.set_ylim(-0.08, 1.1)
+add_grid(ax)
+
+
+# ─── Panel C: Accuracy 2×2 control ──────────────────────────────────────
+
+ax = axes[2]
+ax.set_title("Penalty effect on accuracy", fontsize=9, fontweight="bold")
+
+x_groups = np.array([0, 1])
+width = 0.32
+
+# BP bars
+bp0_m, bp0_s = np.mean(bp_nopen_accs), np.std(bp_nopen_accs, ddof=1)
+bpp_m, bpp_s = np.mean(bp_pen_accs), np.std(bp_pen_accs, ddof=1)
+# DFA bars
+dfa0_m, dfa0_s = np.mean(dfa_nopen_accs), np.std(dfa_nopen_accs, ddof=1)
+dfap_m, dfap_s = np.mean(dfa_pen_accs), np.std(dfa_pen_accs, ddof=1)
+
+bars1 = ax.bar(x_groups - width/2, [bp0_m, dfa0_m], width, yerr=[bp0_s, dfa0_s],
+ capsize=3, color=[C_BP, C_DFA], edgecolor="k", linewidth=0.5,
+ label="$\\lambda=0$", zorder=3)
+bars2 = ax.bar(x_groups + width/2, [bpp_m, dfap_m], width, yerr=[bpp_s, dfap_s],
+ capsize=3, color=[C_BP, C_DFA], edgecolor="k", linewidth=0.5,
+ alpha=0.5, label="$\\lambda=10^{-2}$", zorder=3,
+ hatch="///")
+
+ax.axhline(FROZEN, color="#555", lw=1.2, ls=":", zorder=10)
+ax.text(1.15, FROZEN + 0.012, f"frozen ({FROZEN})", fontsize=7, color="#555", va="bottom", ha="center")
+
+ax.set_xticks(x_groups)
+ax.set_xticklabels(["BP", "DFA"], fontsize=9)
+ax.set_ylabel("Test accuracy")
+ax.set_ylim(0, 0.68)
+ax.legend(loc="upper right", fontsize=7)
+add_grid(ax)
+
+
+# ─── Save ────────────────────────────────────────────────────────────────
+
+out = os.path.join(REPO_ROOT, "paper/figures/fig4_penalty_rescue.pdf")
+fig.savefig(out, bbox_inches="tight", dpi=300)
+fig.savefig(out.replace(".pdf", ".png"), bbox_inches="tight", dpi=200)
+print(f"Saved: {out}")
diff --git a/paper/figures/render_fig_d512L2_panelA.py b/paper/figures/render_fig_d512L2_panelA.py
new file mode 100644
index 0000000..b8fabf8
--- /dev/null
+++ b/paper/figures/render_fig_d512L2_panelA.py
@@ -0,0 +1,92 @@
+"""Panel A style scatter for d=512 L=2 qualifying seeds, with frozen baseline line."""
+import os
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+import matplotlib.patches as mpatches
+import numpy as np
+
+REPO_ROOT = "/home/yurenh2/fa"
+
+# Per-seed data for qualifying seeds 1, 2, 5
+per_seed = {
+ "BP": [{"acc": 0.6061, "gamma": 1.0},
+ {"acc": 0.6076, "gamma": 1.0},
+ {"acc": 0.6065, "gamma": 1.0}],
+ "FA": [{"acc": 0.3471, "gamma": 0.4840},
+ {"acc": 0.3464, "gamma": 0.4721},
+ {"acc": 0.3410, "gamma": 0.4924}],
+ "DFA": [{"acc": 0.2978, "gamma": 0.2062},
+ {"acc": 0.2968, "gamma": 0.1786},
+ {"acc": 0.2963, "gamma": 0.1940}],
+}
+FROZEN = 0.349
+
+COLORS = {"BP": "#2166ac", "FA": "#e08214", "DFA": "#b2182b"}
+MARKERS = {"BP": "o", "FA": "s", "DFA": "D"}
+
+plt.rcParams.update({
+ "font.size": 9, "axes.labelsize": 10, "axes.titlesize": 10,
+ "xtick.labelsize": 8, "ytick.labelsize": 8, "font.family": "serif",
+})
+
+fig, ax = plt.subplots(figsize=(4.0, 3.5))
+
+# Axes swapped: x = Γ (cosine), y = accuracy
+x_lim = (-0.22, 1.12)
+y_lim = (-0.02, 0.72)
+
+# Four quadrants: boundaries at x=0 (cos=0) and y=0.10 (chance)
+ax.fill_between([0, x_lim[1]], 0.10, y_lim[1], color="#c8e6c9", alpha=0.5, zorder=0)
+ax.fill_between([x_lim[0], 0], y_lim[0], 0.10, color="#ffcdd2", alpha=0.5, zorder=0)
+ax.fill_between([x_lim[0], 0], 0.10, y_lim[1], color="#f5f5f5", alpha=0.6, zorder=0)
+ax.fill_between([0, x_lim[1]], y_lim[0], 0.10, color="#f5f5f5", alpha=0.6, zorder=0)
+
+ax.axvline(0, color="gray", lw=0.6, ls="--", zorder=1)
+ax.axhline(0.10, color="gray", lw=0.6, ls="--", zorder=1)
+
+# Frozen baseline horizontal line (acc = FROZEN)
+ax.axhline(FROZEN, color="#555", lw=1.2, ls=":", zorder=2)
+ax.text(1.05, FROZEN + 0.01, f"frozen baseline ({FROZEN:.3f})", fontsize=7,
+ color="#555", ha="right", va="bottom")
+
+# Quadrant labels
+ax.text(-0.11, 0.45, "cos < 0,\nacc > chance", fontsize=6.5, color="#888",
+ ha="center", va="center", style="italic", rotation=90)
+ax.text(0.55, 0.04, "cos > 0,\nacc < chance", fontsize=6.5, color="#888",
+ ha="center", va="center", style="italic")
+ax.text(0.55, 0.45, '"looks like\n learning"', fontsize=7, color="#388e3c",
+ ha="center", va="center", fontweight="bold")
+ax.text(-0.11, 0.04, "neither", fontsize=6.5, color="#c62828",
+ ha="center", va="center", style="italic")
+
+# Plot all 3 seeds per method: x=gamma, y=acc
+for method in ["BP", "FA", "DFA"]:
+ seeds = per_seed[method]
+ gammas = [s["gamma"] for s in seeds]
+ accs = [s["acc"] for s in seeds]
+ ax.scatter(gammas, accs, c=COLORS[method], marker=MARKERS[method],
+ s=60, zorder=5, edgecolors="k", linewidths=0.4, label=method)
+
+# Labels — annotate near the centroid of each cluster
+for method, offsets in [("BP", (-8, 8)), ("FA", (8, -10)), ("DFA", (8, -10))]:
+ seeds = per_seed[method]
+ cx = np.mean([s["gamma"] for s in seeds])
+ cy = np.mean([s["acc"] for s in seeds])
+ ax.annotate(method, (cx, cy),
+ xytext=offsets, textcoords="offset points", fontsize=9, fontweight="bold",
+ color=COLORS[method])
+
+ax.set_xlabel("Aggregate $\\Gamma$ (cosine)")
+ax.set_ylabel("Test accuracy")
+ax.set_xlim(*x_lim)
+ax.set_ylim(*y_lim)
+# No title — user will add caption externally
+
+ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ax.set_axisbelow(True)
+
+out = os.path.join(REPO_ROOT, "paper/figures/fig_d512L2_panelA.pdf")
+fig.savefig(out, bbox_inches="tight", dpi=300)
+fig.savefig(out.replace(".pdf", ".png"), bbox_inches="tight", dpi=200)
+print(f"Saved: {out}")
diff --git a/paper/figures/render_fig_nooutln_temporal.py b/paper/figures/render_fig_nooutln_temporal.py
new file mode 100644
index 0000000..443b5c1
--- /dev/null
+++ b/paper/figures/render_fig_nooutln_temporal.py
@@ -0,0 +1,96 @@
+"""
+Temporal evolution for ResMLP d=256 L=4 WITHOUT terminal LN.
+Separate figure (ablation control for Mode 1b).
+BP / FA / DFA overlaid, 3 columns = ||h_L||, ||g_L||, acc.
+"""
+import os, json
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+import numpy as np
+
+REPO_ROOT = "/home/yurenh2/fa"
+COLORS = {"BP": "#2166ac", "FA": "#e08214", "DFA": "#b2182b"}
+
+plt.rcParams.update({
+ "font.size": 9, "axes.labelsize": 10, "axes.titlesize": 10,
+ "legend.fontsize": 8, "xtick.labelsize": 8, "ytick.labelsize": 8,
+ "font.family": "serif",
+})
+
+
+def extract_series(log):
+ epochs = [e['epoch'] for e in log]
+ if 'hidden_norms' in log[0]:
+ h_L = [e['hidden_norms'][-1] for e in log]
+ else:
+ h_L = [1.0] * len(log)
+ if 'bp_grad_norms_per_sample_med' in log[0]:
+ g_L = [e['bp_grad_norms_per_sample_med'][-1] for e in log]
+ elif 'bp_grad_per_sample_l2_med' in log[0]:
+ g_L = [e['bp_grad_per_sample_l2_med'][-1] for e in log]
+ else:
+ g_L = [1.0] * len(log)
+ acc = [e['acc_eval'] for e in log]
+ return epochs, h_L, g_L, acc
+
+
+noln = json.load(open(os.path.join(REPO_ROOT, "results/snapshot_no_outln_v1/snapshot_noLN_s42.json")))
+
+# Try canonical FA; fall back to BP/DFA only
+fa_path = os.path.join(REPO_ROOT, "results/snapshot_no_outln_v1/snapshot_fa_canonical_noln_s42.json")
+has_fa = os.path.exists(fa_path)
+if has_fa:
+ fa_noln = json.load(open(fa_path))
+
+data = {"BP": extract_series(noln['bp_log']), "DFA": extract_series(noln['dfa_log'])}
+if has_fa:
+ data["FA"] = extract_series(fa_noln['fa_log'])
+methods = ["BP", "FA", "DFA"] if has_fa else ["BP", "DFA"]
+
+fig, axes = plt.subplots(1, 3, figsize=(10.5, 2.8))
+fig.subplots_adjust(wspace=0.35, left=0.07, right=0.97, bottom=0.18, top=0.92)
+
+# Column 0: ||h_L||
+ax = axes[0]
+for m in methods:
+ ep, h, g, a = data[m]
+ ax.semilogy(ep, h, color=COLORS[m], linewidth=1.5, label=m)
+ax.set_ylabel("$\\|h_L\\|_2$")
+ax.set_xlabel("Epoch")
+ax.set_title("$\\|h_L\\|$ (residual norm)")
+ax.legend(loc="center right", fontsize=7)
+ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ax.grid(True, which="minor", color="#e8e8e8", linewidth=0.3, linestyle=":")
+ax.set_axisbelow(True)
+
+# Column 1: ||g_L||
+ax = axes[1]
+for m in methods:
+ ep, h, g, a = data[m]
+ ax.semilogy(ep, g, color=COLORS[m], linewidth=1.5, label=m)
+ax.set_ylabel("$\\|g_L\\|_2$")
+ax.set_xlabel("Epoch")
+ax.set_title("$\\|g_L\\|$ (BP gradient at $h_L$)")
+ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ax.grid(True, which="minor", color="#e8e8e8", linewidth=0.3, linestyle=":")
+ax.set_axisbelow(True)
+
+# Column 2: test acc
+ax = axes[2]
+for m in methods:
+ ep, h, g, a = data[m]
+ ax.plot(ep, a, color=COLORS[m], linewidth=1.5, label=m)
+ax.set_ylabel("Test accuracy")
+ax.set_xlabel("Epoch")
+ax.set_title("Test accuracy")
+ax.set_ylim(0, 0.7)
+ax.grid(True, which="major", color="#d0d0d0", linewidth=0.4, linestyle=":")
+ax.set_axisbelow(True)
+
+out = os.path.join(REPO_ROOT, "paper/figures/fig_nooutln_temporal.pdf")
+fig.savefig(out, bbox_inches="tight", dpi=300)
+fig.savefig(out.replace(".pdf", ".png"), bbox_inches="tight", dpi=200)
+print(f"Saved: {out}")
+if not has_fa:
+ print("NOTE: FA canonical data not yet available — will re-render when ready")
diff --git a/paper/main.log b/paper/main.log
new file mode 100644
index 0000000..34a2606
--- /dev/null
+++ b/paper/main.log
@@ -0,0 +1,595 @@
+**
+(main.tex
+LaTeX2e <2021-11-15> patch level 1
+L3 programming layer <2022-02-24> (article.cls
+Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
+(size10.clo
+File: size10.clo 2021/10/04 v1.4n Standard LaTeX file (size option)
+)
+\c@part=\count181
+\c@section=\count182
+\c@subsection=\count183
+\c@subsubsection=\count184
+\c@paragraph=\count185
+\c@subparagraph=\count186
+\c@figure=\count187
+\c@table=\count188
+\abovecaptionskip=\skip47
+\belowcaptionskip=\skip48
+\bibindent=\dimen138
+) (neurips_2026.sty
+Package: neurips_2026 2026-01-29 NeurIPS 2026 submission/camera-ready style fil
+e
+ (environ.sty
+Package: environ 2014/05/04 v0.3 A new way to define environments
+ (trimspaces.sty
+Package: trimspaces 2009/09/17 v1.1 Trim spaces around a token list
+)
+\@envbody=\toks16
+) (natbib.sty
+Package: natbib 2010/09/13 8.31b (PWD, AO)
+\bibhang=\skip49
+\bibsep=\skip50
+LaTeX Info: Redefining \cite on input line 694.
+\c@NAT@ctr=\count189
+)
+(geometry.sty
+Package: geometry 2020/01/02 v5.9 Page Geometry
+ (keyval.sty
+Package: keyval 2014/10/28 v1.15 key=value parser (DPC)
+\KV@toks@=\toks17
+) (ifvtex.sty
+Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead.
+ (iftex.sty
+Package: iftex 2022/02/03 v1.0f TeX engine tests
+))
+\Gm@cnth=\count190
+\Gm@cntv=\count191
+\c@Gm@tempcnt=\count192
+\Gm@bindingoffset=\dimen139
+\Gm@wd@mp=\dimen140
+\Gm@odd@mp=\dimen141
+\Gm@even@mp=\dimen142
+\Gm@layoutwidth=\dimen143
+\Gm@layoutheight=\dimen144
+\Gm@layouthoffset=\dimen145
+\Gm@layoutvoffset=\dimen146
+\Gm@dimlist=\toks18
+)
+\@neuripsabovecaptionskip=\skip51
+\@neuripsbelowcaptionskip=\skip52
+ (lineno.sty
+Package: lineno 2005/11/02 line numbers on paragraphs v4.41
+Invalid UTF-8 byte or sequence at line 296 replaced by U+FFFD.
+\linenopenalty=\count193
+\output=\toks19
+\linenoprevgraf=\count194
+\linenumbersep=\dimen147
+\linenumberwidth=\dimen148
+\c@linenumber=\count195
+\c@pagewiselinenumber=\count196
+\c@LN@truepage=\count197
+\c@internallinenumber=\count198
+\c@internallinenumbers=\count199
+\quotelinenumbersep=\dimen149
+\bframerule=\dimen150
+\bframesep=\dimen151
+\bframebox=\box50
+LaTeX Info: Redefining \\ on input line 3056.
+))
+(inputenc.sty
+Package: inputenc 2021/02/14 v1.3d Input encoding file
+\inpenc@prehook=\toks20
+\inpenc@posthook=\toks21
+
+
+Package inputenc Warning: inputenc package ignored with utf8 based engines.
+
+) (fontenc.sty
+Package: fontenc 2021/04/29 v2.0v Standard LaTeX package
+LaTeX Font Info: Trying to load font information for T1+ptm on input line 11
+2.
+ (t1ptm.fd
+File: t1ptm.fd 2001/06/04 font definitions for T1/ptm.
+)) (hyperref.sty
+Package: hyperref 2022-02-21 v7.00n Hypertext links for LaTeX
+ (ltxcmds.sty
+Package: ltxcmds 2020-05-10 v1.25 LaTeX kernel commands for general use (HO)
+) (pdftexcmds.sty
+Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO
+)
+
+(infwarerr.sty
+Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO)
+)
+Package pdftexcmds Info: \pdf@primitive is available.
+Package pdftexcmds Info: \pdf@ifprimitive is available.
+Package pdftexcmds Info: \pdfdraftmode not found.
+) (kvsetkeys.sty
+Package: kvsetkeys 2019/12/15 v1.18 Key value parser (HO)
+) (kvdefinekeys.sty
+Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO)
+) (pdfescape.sty
+Package: pdfescape 2019/12/09 v1.15 Implements pdfTeX's escape features (HO)
+)
+(hycolor.sty
+Package: hycolor 2020-01-27 v1.10 Color options for hyperref/bookmark (HO)
+) (letltxmacro.sty
+Package: letltxmacro 2019/12/03 v1.6 Let assignment for LaTeX macros (HO)
+) (auxhook.sty
+Package: auxhook 2019-12-17 v1.6 Hooks for auxiliary files (HO)
+) (kvoptions.sty
+Package: kvoptions 2020-10-07 v3.14 Key value format for package options (HO)
+)
+\@linkdim=\dimen152
+\Hy@linkcounter=\count266
+\Hy@pagecounter=\count267
+ (pd1enc.def
+File: pd1enc.def 2022-02-21 v7.00n Hyperref: PDFDocEncoding definition (HO)
+)
+(intcalc.sty
+Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO)
+) (etexcmds.sty
+Package: etexcmds 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO)
+)
+\Hy@SavedSpaceFactor=\count268
+ (puenc.def
+File: puenc.def 2022-02-21 v7.00n Hyperref: PDF Unicode definition (HO)
+)
+Package hyperref Info: Hyper figures OFF on input line 4137.
+Package hyperref Info: Link nesting OFF on input line 4142.
+Package hyperref Info: Hyper index ON on input line 4145.
+Package hyperref Info: Plain pages OFF on input line 4152.
+Package hyperref Info: Backreferencing OFF on input line 4157.
+Package hyperref Info: Implicit mode ON; LaTeX internals redefined.
+Package hyperref Info: Bookmarks ON on input line 4390.
+\c@Hy@tempcnt=\count269
+ (url.sty
+\Urlmuskip=\muskip16
+Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc.
+)
+LaTeX Info: Redefining \url on input line 4749.
+\XeTeXLinkMargin=\dimen153
+ (bitset.sty
+Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO)
+ (bigintcalc.sty
+Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO
+)
+))
+\Fld@menulength=\count270
+\Field@Width=\dimen154
+\Fld@charsize=\dimen155
+Package hyperref Info: Hyper figures OFF on input line 6027.
+Package hyperref Info: Link nesting OFF on input line 6032.
+Package hyperref Info: Hyper index ON on input line 6035.
+Package hyperref Info: backreferencing OFF on input line 6042.
+Package hyperref Info: Link coloring OFF on input line 6047.
+Package hyperref Info: Link coloring with OCG OFF on input line 6052.
+Package hyperref Info: PDF/A mode OFF on input line 6057.
+LaTeX Info: Redefining \ref on input line 6097.
+LaTeX Info: Redefining \pageref on input line 6101.
+ (atbegshi-ltx.sty
+Package: atbegshi-ltx 2021/01/10 v1.0c Emulation of the original atbegshi
+package with kernel methods
+)
+\Hy@abspage=\count271
+\c@Item=\count272
+\c@Hfootnote=\count273
+)
+Package hyperref Info: Driver (autodetected): hxetex.
+ (hxetex.def
+File: hxetex.def 2022-02-21 v7.00n Hyperref driver for XeTeX
+ (stringenc.sty
+Package: stringenc 2019/11/29 v1.12 Convert strings between diff. encodings (HO
+)
+)
+\pdfm@box=\box51
+\c@Hy@AnnotLevel=\count274
+\HyField@AnnotCount=\count275
+\Fld@listcount=\count276
+\c@bookmark@seq@number=\count277
+ (rerunfilecheck.sty
+Package: rerunfilecheck 2019/12/05 v1.9 Rerun checks for auxiliary files (HO)
+
+(atveryend-ltx.sty
+Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend pac
+kage
+with kernel methods
+) (uniquecounter.sty
+Package: uniquecounter 2019/12/15 v1.4 Provide unlimited unique counter (HO)
+)
+Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2
+86.
+)
+\Hy@SectionHShift=\skip53
+) (booktabs.sty
+Package: booktabs 2020/01/12 v1.61803398 Publication quality tables
+\heavyrulewidth=\dimen156
+\lightrulewidth=\dimen157
+\cmidrulewidth=\dimen158
+\belowrulesep=\dimen159
+\belowbottomsep=\dimen160
+\aboverulesep=\dimen161
+\abovetopsep=\dimen162
+\cmidrulesep=\dimen163
+\cmidrulekern=\dimen164
+\defaultaddspace=\dimen165
+\@cmidla=\count278
+\@cmidlb=\count279
+\@aboverulesep=\dimen166
+\@belowrulesep=\dimen167
+\@thisruleclass=\count280
+\@lastruleclass=\count281
+\@thisrulewidth=\dimen168
+) (float.sty
+Package: float 2001/11/08 v1.3d Float enhancements (AL)
+\c@float@type=\count282
+\float@exts=\toks22
+\float@box=\box52
+\@float@everytoks=\toks23
+\@floatcapt=\box53
+)
+(tabularx.sty
+Package: tabularx 2020/01/15 v2.11c `tabularx' package (DPC)
+ (array.sty
+Package: array 2021/10/04 v2.5f Tabular extension package (FMi)
+\col@sep=\dimen169
+\ar@mcellbox=\box54
+\extrarowheight=\dimen170
+\NC@list=\toks24
+\extratabsurround=\skip54
+\backup@length=\skip55
+\ar@cellbox=\box55
+)
+\TX@col@width=\dimen171
+\TX@old@table=\dimen172
+\TX@old@col=\dimen173
+\TX@target=\dimen174
+\TX@delta=\dimen175
+\TX@cols=\count283
+\TX@ftn=\toks25
+) (amsfonts.sty
+Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support
+\@emptytoks=\toks26
+\symAMSa=\mathgroup4
+\symAMSb=\mathgroup5
+LaTeX Font Info: Redeclaring math symbol \hbar on input line 98.
+LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold'
+(Font) U/euf/m/n --> U/euf/b/n on input line 106.
+) (amsmath.sty
+Package: amsmath 2021/10/15 v2.17l AMS math features
+\@mathmargin=\skip56
+
+For additional information on amsmath, use the `?' option.
+(amstext.sty
+Package: amstext 2021/08/26 v2.01 AMS text
+ (amsgen.sty
+File: amsgen.sty 1999/11/30 v2.0 generic functions
+\@emptytoks=\toks27
+\ex@=\dimen176
+)) (amsbsy.sty
+Package: amsbsy 1999/11/29 v1.2d Bold Symbols
+\pmbraise@=\dimen177
+) (amsopn.sty
+Package: amsopn 2021/08/26 v2.02 operator names
+)
+\inf@bad=\count284
+LaTeX Info: Redefining \frac on input line 234.
+\uproot@=\count285
+\leftroot@=\count286
+LaTeX Info: Redefining \overline on input line 399.
+\classnum@=\count287
+\DOTSCASE@=\count288
+LaTeX Info: Redefining \ldots on input line 496.
+LaTeX Info: Redefining \dots on input line 499.
+LaTeX Info: Redefining \cdots on input line 620.
+\Mathstrutbox@=\box56
+\strutbox@=\box57
+\big@size=\dimen178
+LaTeX Font Info: Redeclaring font encoding OML on input line 743.
+LaTeX Font Info: Redeclaring font encoding OMS on input line 744.
+\macc@depth=\count289
+\c@MaxMatrixCols=\count290
+\dotsspace@=\muskip17
+\c@parentequation=\count291
+\dspbrk@lvl=\count292
+\tag@help=\toks28
+\row@=\count293
+\column@=\count294
+\maxfields@=\count295
+\andhelp@=\toks29
+\eqnshift@=\dimen179
+\alignsep@=\dimen180
+\tagshift@=\dimen181
+\tagwidth@=\dimen182
+\totwidth@=\dimen183
+\lineht@=\dimen184
+\@envbody=\toks30
+\multlinegap=\skip57
+\multlinetaggap=\skip58
+\mathdisplay@stack=\toks31
+LaTeX Info: Redefining \[ on input line 2938.
+LaTeX Info: Redefining \] on input line 2939.
+) (amssymb.sty
+Package: amssymb 2013/01/14 v3.01 AMS font symbols
+)
+(microtype.sty
+Package: microtype 2022/03/14 v3.0d Micro-typographical refinements (RS)
+ (etoolbox.sty
+Package: etoolbox 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW)
+\etb@tempcnta=\count296
+)
+\MT@toks=\toks32
+\MT@tempbox=\box58
+\MT@count=\count297
+LaTeX Info: Redefining \noprotrusionifhmode on input line 1027.
+LaTeX Info: Redefining \leftprotrusion on input line 1028.
+LaTeX Info: Redefining \rightprotrusion on input line 1036.
+LaTeX Info: Redefining \textls on input line 1195.
+\MT@outer@kern=\dimen185
+LaTeX Info: Redefining \textmicrotypecontext on input line 1781.
+\MT@listname@count=\count298
+ (microtype-xetex.def
+File: microtype-xetex.def 2022/03/14 v3.0d Definitions specific to xetex (RS)
+LaTeX Info: Redefining \lsstyle on input line 236.
+)
+Package microtype Info: Loading configuration file microtype.cfg.
+ (microtype.cfg
+File: microtype.cfg 2022/03/14 v3.0d microtype main configuration file (RS)
+))
+(xcolor.sty
+Package: xcolor 2021/10/31 v2.13 LaTeX color extensions (UK)
+ (color.cfg
+File: color.cfg 2016/01/02 v1.6 sample color configuration
+)
+Package xcolor Info: Driver file: xetex.def on input line 227.
+ (xetex.def
+File: xetex.def 2021/03/18 v5.0k Graphics/color driver for xetex
+)
+Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1352.
+Package xcolor Info: Model `RGB' extended on input line 1368.
+Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1370.
+Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1371.
+Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1372.
+Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1373.
+Package xcolor Info: Model `Gray' substituted by `gray' on input line 1374.
+Package xcolor Info: Model `wave' substituted by `hsb' on input line 1375.
+) (graphicx.sty
+Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR)
+ (graphics.sty
+Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR)
+ (trig.sty
+Package: trig 2021/08/11 v1.11 sin cos tan (DPC)
+)
+(graphics.cfg
+File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration
+)
+Package graphics Info: Driver file: xetex.def on input line 107.
+)
+\Gin@req@height=\dimen186
+\Gin@req@width=\dimen187
+) (l3backend-xetex.def
+File: l3backend-xetex.def 2022-02-07 L3 backend support: XeTeX
+\c__kernel_sys_dvipdfmx_version_int=\count299
+\l__color_backend_stack_int=\count300
+\g__color_backend_stack_int=\count301
+\g__graphics_track_int=\count302
+\l__pdf_internal_box=\box59
+\g__pdf_backend_object_int=\count303
+\g__pdf_backend_annotation_int=\count304
+\g__pdf_backend_link_int=\count305
+) (main.aux)
+\openout1 = `main.aux'.
+
+LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 25.
+LaTeX Font Info: Trying to load font information for TS1+cmr on input line 2
+5.
+ (ts1cmr.fd
+File: ts1cmr.fd 2019/12/16 v2.5j Standard LaTeX font definitions
+)
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for TU/lmr/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 25.
+LaTeX Font Info: ... okay on input line 25.
+
+*geometry* driver: auto-detecting
+*geometry* detected driver: xetex
+*geometry* verbose mode - [ preamble ] result:
+* driver: xetex
+* paper: letterpaper
+* layout: <same size as paper>
+* layoutoffset:(h,v)=(0.0pt,0.0pt)
+* modes:
+* h-part:(L,W,R)=(92.14519pt, 430.00462pt, 92.14519pt)
+* v-part:(T,H,B)=(95.39737pt, 556.47656pt, 143.09605pt)
+* \paperwidth=614.295pt
+* \paperheight=794.96999pt
+* \textwidth=430.00462pt
+* \textheight=556.47656pt
+* \oddsidemargin=19.8752pt
+* \evensidemargin=19.8752pt
+* \topmargin=-13.87262pt
+* \headheight=12.0pt
+* \headsep=25.0pt
+* \topskip=10.0pt
+* \footskip=30.0pt
+* \marginparwidth=65.0pt
+* \marginparsep=11.0pt
+* \columnsep=10.0pt
+* \skip\footins=9.0pt plus 4.0pt minus 2.0pt
+* \hoffset=0.0pt
+* \voffset=0.0pt
+* \mag=1000
+* \@twocolumnfalse
+* \@twosidefalse
+* \@mparswitchfalse
+* \@reversemarginfalse
+* (1in=72.27pt=25.4mm, 1cm=28.453pt)
+
+*geometry* verbose mode - [ newgeometry ] result:
+* driver: xetex
+* paper: letterpaper
+* layout: <same size as paper>
+* layoutoffset:(h,v)=(0.0pt,0.0pt)
+* modes:
+* h-part:(L,W,R)=(108.405pt, 397.48499pt, 108.40501pt)
+* v-part:(T,H,B)=(72.26999pt, 650.43pt, 72.27pt)
+* \paperwidth=614.295pt
+* \paperheight=794.96999pt
+* \textwidth=397.48499pt
+* \textheight=650.43pt
+* \oddsidemargin=36.13501pt
+* \evensidemargin=36.13501pt
+* \topmargin=-37.0pt
+* \headheight=12.0pt
+* \headsep=25.0pt
+* \topskip=10.0pt
+* \footskip=30.0pt
+* \marginparwidth=65.0pt
+* \marginparsep=11.0pt
+* \columnsep=10.0pt
+* \skip\footins=9.0pt plus 4.0pt minus 2.0pt
+* \hoffset=0.0pt
+* \voffset=0.0pt
+* \mag=1000
+* \@twocolumnfalse
+* \@twosidefalse
+* \@mparswitchfalse
+* \@reversemarginfalse
+* (1in=72.27pt=25.4mm, 1cm=28.453pt)
+
+Package hyperref Info: Link coloring OFF on input line 25.
+(nameref.sty
+Package: nameref 2021-04-02 v2.47 Cross-referencing by name of section
+ (refcount.sty
+Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO)
+) (gettitlestring.sty
+Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO)
+)
+\c@section@level=\count306
+)
+LaTeX Info: Redefining \ref on input line 25.
+LaTeX Info: Redefining \pageref on input line 25.
+LaTeX Info: Redefining \nameref on input line 25.
+ (main.out) (main.out)
+\@outlinefile=\write3
+\openout3 = `main.out'.
+
+LaTeX Info: Redefining \microtypecontext on input line 25.
+Package microtype Info: Applying patch `item' on input line 25.
+Package microtype Info: Applying patch `toc' on input line 25.
+Package microtype Info: Applying patch `eqnum' on input line 25.
+Package microtype Info: Applying patch `footnote' on input line 25.
+Package microtype Info: Character protrusion enabled (level 2).
+Package microtype Info: Using default protrusion set `alltext'.
+Package microtype Info: No adjustment of tracking.
+Package microtype Info: No adjustment of spacing.
+Package microtype Info: No adjustment of kerning.
+
+(mt-ptm.cfg
+File: mt-ptm.cfg 2006/04/20 v1.7 microtype config. file: Times (RS)
+) (mt-cmr.cfg
+File: mt-cmr.cfg 2013/05/19 v2.2 microtype config. file: Computer Modern Roman
+(RS)
+)
+LaTeX Font Info: Trying to load font information for U+msa on input line 28.
+
+ (umsa.fd
+File: umsa.fd 2013/01/14 v3.01 AMS symbols A
+) (mt-msa.cfg
+File: mt-msa.cfg 2006/02/04 v1.1 microtype config. file: AMS symbols (a) (RS)
+)
+LaTeX Font Info: Trying to load font information for U+msb on input line 28.
+
+ (umsb.fd
+File: umsb.fd 2013/01/14 v3.01 AMS symbols B
+) (mt-msb.cfg
+File: mt-msb.cfg 2005/06/01 v1.0 microtype config. file: AMS symbols (b) (RS)
+)
+LaTeX Font Info: Trying to load font information for T1+lmtt on input line 2
+8.
+
+(t1lmtt.fd
+File: t1lmtt.fd 2015/05/01 v1.6.1 Font defs for Latin Modern
+)
+Package microtype Info: Loading generic protrusion settings for font family
+(microtype) `lmtt' (encoding: T1).
+(microtype) For optimal results, create family-specific settings.
+(microtype) See the microtype manual for details.
+LaTeX Font Info: Trying to load font information for T1+phv on input line 31
+.
+ (t1phv.fd
+File: t1phv.fd 2020/03/25 scalable font definitions for T1/phv.
+)
+Package microtype Info: Loading generic protrusion settings for font family
+(microtype) `phv' (encoding: T1).
+(microtype) For optimal results, create family-specific settings.
+(microtype) See the microtype manual for details.
+ [1
+
+
+] [2]
+File: figures/figure_audit_5method.png Graphic file (type bmp)
+<figures/figure_audit_5method.png>
+ [3]
+Underfull \vbox (badness 1694) has occurred while \output is active []
+
+ [4]
+[5] [6]
+File: figures/figure_cross_arch_temporal_s42.png Graphic file (type bmp)
+<figures/figure_cross_arch_temporal_s42.png>
+File: figures/fig4_penalty_rescue.pdf Graphic file (type pdf)
+<use figures/fig4_penalty_rescue.pdf>
+File: figures/fig5_cross_arch_summary.pdf Graphic file (type pdf)
+<use figures/fig5_cross_arch_summary.pdf>
+ [7] [8]
+Underfull \vbox (badness 1859) has occurred while \output is active []
+
+ [9]
+Underfull \hbox (badness 10000) in paragraph at lines 295--296
+\T1/ptm/m/n/10 We will re-lease a ref-er-ence im-ple-men-ta-tion at []$\T1/lmtt
+/m/n/10 https : / / github . com /
+ []
+
+[10] [11]
+File: figures/fig2_decision_utility.pdf Graphic file (type pdf)
+<use figures/fig2_decision_utility.pdf>
+
+
+LaTeX Warning: `h' float specifier changed to `ht'.
+
+
+Underfull \vbox (badness 10000) has occurred while \output is active []
+
+ [12]
+
+LaTeX Warning: `h' float specifier changed to `ht'.
+
+[13]
+
+LaTeX Warning: `h' float specifier changed to `ht'.
+
+[14] [15]
+
+LaTeX Warning: `h' float specifier changed to `ht'.
+
+[16] [17] [18] (main.aux)
+Package rerunfilecheck Info: File `main.out' has not changed.
+(rerunfilecheck) Checksum: 278358DBB8F5E733350CF37CA529BF7E;4171.
+ )
+Output written on main.xdv (18 pages, 153824 bytes).