summaryrefslogtreecommitdiff
path: root/research/flossing/analyze_separate.py
diff options
context:
space:
mode:
authorYurenHao0426 <blackhao0426@gmail.com>2026-06-13 12:35:36 -0500
committerYurenHao0426 <blackhao0426@gmail.com>2026-06-13 12:35:36 -0500
commit66e0d8b9fd4d0f7a2231d689c055e26fdf1cf04a (patch)
treec29cba61124018755a19b02c9d33e3ad5f2e05cc /research/flossing/analyze_separate.py
rrm workspace: TRM/HRM/SRM code, Maze dataset, dynamical-analysis pipelineHEADmain
Curated export for clone-and-run Maze training (2x A6000) + diagnostics. trm/hrm pretrain.py carry trajectory-augmentation code (backward-compatible). Heavy artifacts (checkpoints/wandb/npz) gitignored; see PROVENANCE.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'research/flossing/analyze_separate.py')
-rw-r--r--research/flossing/analyze_separate.py124
1 files changed, 124 insertions, 0 deletions
diff --git a/research/flossing/analyze_separate.py b/research/flossing/analyze_separate.py
new file mode 100644
index 0000000..d5759ab
--- /dev/null
+++ b/research/flossing/analyze_separate.py
@@ -0,0 +1,124 @@
+"""Analyze separated λ_L and λ_H, and their predictive power for failure."""
+import numpy as np
+import matplotlib
+matplotlib.use("Agg")
+import matplotlib.pyplot as plt
+from scipy import stats
+import glob, os
+
+ROOT = "/home/yurenh2/rrm/research/flossing"
+OUT = f"{ROOT}/plots_separate"
+os.makedirs(OUT, exist_ok=True)
+
+files = sorted(glob.glob(f"{ROOT}/diag_sep_1k_shard*.npz"))
+m = {}
+for f in files:
+ d = np.load(f)
+ for k in d.files: m.setdefault(k, []).append(d[k])
+for k in list(m.keys()): m[k] = np.concatenate(m[k], 0)
+np.savez_compressed(f"{ROOT}/diag_sep_1k.npz", **m)
+
+N = len(m["exact_correct"])
+exact = m["exact_correct"].astype(bool)
+acc = exact.mean()
+print(f"N={N} acc={acc:.4f}\n")
+
+def auc(score, target):
+ return stats.mannwhitneyu(score[target], score[~target], alternative="greater").statistic / (target.sum() * (~target).sum())
+
+results = {}
+for name in ["lyap_joint", "lyap_L", "lyap_H"]:
+ ls = m[name]
+ print(f"== {name} ==")
+ print(f"{'i':>3} {'mean_all':>10} {'mean_succ':>10} {'mean_fail':>10} {'Δ':>8} {'AUROC':>7} {'cohen_d':>8}")
+ for i in range(ls.shape[1]):
+ li = ls[:, i]; s_ = li[exact]; f_ = li[~exact]
+ pooled = np.sqrt(((s_.size-1)*s_.var() + (f_.size-1)*f_.var()) / (s_.size+f_.size-2))
+ dc = (s_.mean() - f_.mean()) / pooled
+ delta = f_.mean() - s_.mean()
+ au = auc(li, ~exact)
+ print(f"{i+1:>3} {li.mean():+10.4f} {s_.mean():+10.4f} {f_.mean():+10.4f} {delta:+8.4f} {au:>7.3f} {abs(dc):>8.3f}")
+ results[name] = ls
+ print()
+
+# AUROC comparison
+print("=== Single-feature AUROC predicting failure ===")
+for name in ["lyap_joint", "lyap_L", "lyap_H"]:
+ ls = m[name]
+ for label, score in [("λ_1", ls[:, 0]), ("mean", ls.mean(1)), ("λ_K", ls[:, -1])]:
+ print(f" {name}.{label:6s}: AUROC = {auc(score, ~exact):.4f}")
+
+# --- plot 1: three spectra overlay ---
+fig, axes = plt.subplots(1, 3, figsize=(15, 4.5), sharex=True)
+for ax, name in zip(axes, ["lyap_joint", "lyap_L", "lyap_H"]):
+ ls = m[name]
+ K = ls.shape[1]
+ x = np.arange(1, K+1)
+ s_ = ls[exact]; f_ = ls[~exact]
+ ax.fill_between(x, s_.mean(0)-s_.std(0), s_.mean(0)+s_.std(0), color="C0", alpha=0.25)
+ ax.plot(x, s_.mean(0), "C0-o", label="succ", lw=2)
+ ax.fill_between(x, f_.mean(0)-f_.std(0), f_.mean(0)+f_.std(0), color="C3", alpha=0.25)
+ ax.plot(x, f_.mean(0), "C3-o", label="fail", lw=2)
+ ax.axhline(0, color="k", ls="--", lw=1, label="critical")
+ ax.set_xlabel("λ index")
+ ax.set_ylabel(r"$\lambda_i$ (per cycle)")
+ ax.set_title(name)
+ ax.legend()
+ ax.grid(alpha=0.3)
+fig.suptitle(f"HRM step_26040 — separated Lyapunov spectra (N={N}, acc={acc:.2%})")
+fig.tight_layout()
+fig.savefig(f"{OUT}/three_spectra.png", dpi=130)
+plt.close()
+
+# --- plot 2: λ_H_1 histogram (the differentiator) ---
+fig, ax = plt.subplots(1, 1, figsize=(7, 4))
+ls = m["lyap_H"][:, 0]
+lo = ls.min(); hi = ls.max()
+bins = np.linspace(lo, hi, 60)
+ax.hist(ls[exact], bins=bins, alpha=0.55, label=f"succ", color="C0", density=True)
+ax.hist(ls[~exact], bins=bins, alpha=0.55, label=f"fail", color="C3", density=True)
+ax.axvline(0, color="k", ls="--", lw=1)
+ax.axvline(ls[exact].mean(), color="C0", ls=":", lw=1)
+ax.axvline(ls[~exact].mean(), color="C3", ls=":", lw=1)
+ax.set_xlabel(r"$\lambda_{H,1}$ — H subsystem top Lyapunov")
+ax.set_ylabel("density")
+ax.set_title(f"H-module Lyapunov is the differentiator (AUROC={auc(ls, ~exact):.3f})")
+ax.legend()
+fig.tight_layout()
+fig.savefig(f"{OUT}/lyap_H_hist.png", dpi=130)
+plt.close()
+
+# --- plot 3: λ_L_1 histogram (NOT a differentiator) ---
+fig, ax = plt.subplots(1, 1, figsize=(7, 4))
+ls = m["lyap_L"][:, 0]
+lo = ls.min(); hi = ls.max()
+bins = np.linspace(lo, hi, 60)
+ax.hist(ls[exact], bins=bins, alpha=0.55, label=f"succ", color="C0", density=True)
+ax.hist(ls[~exact], bins=bins, alpha=0.55, label=f"fail", color="C3", density=True)
+ax.axvline(ls[exact].mean(), color="C0", ls=":", lw=1)
+ax.axvline(ls[~exact].mean(), color="C3", ls=":", lw=1)
+ax.set_xlabel(r"$\lambda_{L,1}$ — L subsystem top Lyapunov")
+ax.set_ylabel("density")
+ax.set_title(f"L-module Lyapunov is NOT a differentiator (AUROC={auc(ls, ~exact):.3f})")
+ax.legend()
+fig.tight_layout()
+fig.savefig(f"{OUT}/lyap_L_hist.png", dpi=130)
+plt.close()
+
+# --- plot 4: scatter λ_L vs λ_H, colored by success/failure ---
+fig, ax = plt.subplots(1, 1, figsize=(7, 6))
+xL = m["lyap_L"][:, 0]
+xH = m["lyap_H"][:, 0]
+ax.scatter(xL[exact], xH[exact], s=5, alpha=0.4, color="C0", label="succ")
+ax.scatter(xL[~exact], xH[~exact], s=5, alpha=0.4, color="C3", label="fail")
+ax.axhline(0, color="k", ls="--", lw=0.5)
+ax.set_xlabel(r"$\lambda_{L,1}$ (L subsystem)")
+ax.set_ylabel(r"$\lambda_{H,1}$ (H subsystem)")
+ax.set_title("Success/failure separates along the λ_H axis")
+ax.legend()
+ax.grid(alpha=0.3)
+fig.tight_layout()
+fig.savefig(f"{OUT}/lyap_L_vs_H_scatter.png", dpi=130)
+plt.close()
+
+print(f"\nplots → {OUT}/")