mirror of
https://github.com/wassname/evil_MoE.git
synced 2026-06-27 19:47:33 +08:00
plot: longrun A4 fig + visible route2 hack≡0 line + committed CSV data source
plot_dynamics now dumps the plotted series to <out>.csv next to the png so the figure is reproducible from a tracked artifact (logs/ and out/runs/ are gitignored). ylim floor -0.035 + 'hack ≡ 0' annotation so route2's pinned-at-zero hack line is visible rather than hidden under the axis. Co-Authored-By: Claudypoo <288921227+claudypoo@users.noreply.github.com>
This commit is contained in:
@@ -222,6 +222,24 @@ def _series_panel(ax, runs, cols, colors, ylim, label_series=False):
|
||||
ax.set_ylim(*ylim)
|
||||
|
||||
|
||||
def dump_data(runs: list[dict], out: Path) -> Path:
|
||||
"""Write the plotted series to a tidy CSV next to the figure so the figure is
|
||||
reproducible from a committed artifact -- logs/ and out/runs/ are gitignored,
|
||||
this CSV is not (it lands in out/figs/, which is tracked)."""
|
||||
csv = out.with_suffix(".csv")
|
||||
lines = ["arm,seed,step,hack,solve"]
|
||||
for r in runs:
|
||||
arm = classify(r)
|
||||
hk = r.get("hack_s"); sv = r.get("gt_s")
|
||||
for i, step in enumerate(r["steps"]):
|
||||
h = hk[i] if hk is not None and i < len(hk) else float("nan")
|
||||
s = sv[i] if sv is not None and i < len(sv) else float("nan")
|
||||
lines.append(f"{arm},{r['seed']},{int(step)},{h},{s}")
|
||||
csv.write_text("\n".join(lines) + "\n")
|
||||
logger.info(f"wrote {csv} ({len(runs)} runs, reproducibility source)")
|
||||
return csv
|
||||
|
||||
|
||||
def plot(runs: list[dict], out: Path) -> None:
|
||||
by_arm: dict[str, list[dict]] = defaultdict(list)
|
||||
for r in runs:
|
||||
@@ -229,6 +247,7 @@ def plot(runs: list[dict], out: Path) -> None:
|
||||
arms = [a for a in ARM_ORDER if a in by_arm]
|
||||
if not arms:
|
||||
raise SystemExit("no runs classified into arms")
|
||||
dump_data(runs, out)
|
||||
|
||||
fig, axes = plt.subplots(1, len(arms), figsize=(3.0 * len(arms), 2.6),
|
||||
sharex=True, sharey=True, squeeze=False)
|
||||
@@ -237,7 +256,17 @@ def plot(runs: list[dict], out: Path) -> None:
|
||||
rs = by_arm[arm]
|
||||
n_seed = len({r["seed"] for r in rs})
|
||||
ax.set_title(f"{arm}\n(n={n_seed} seed{'s' if n_seed > 1 else ''})", fontsize=9)
|
||||
_series_panel(ax, rs, RATE_COLS, RATE_COLORS, ylim=(0, 1), label_series=(col == 0))
|
||||
# ylim floor slightly below 0 so a pinned-at-zero series (route2 hack) draws
|
||||
# ABOVE the axis line instead of hiding under it -- the whole result is that
|
||||
# red sits on zero, so it must be visible, not absent.
|
||||
_series_panel(ax, rs, RATE_COLS, RATE_COLORS, ylim=(-0.035, 1.0), label_series=(col == 0))
|
||||
# If hack is pinned at zero all panel, say so -- else "no red line" reads as
|
||||
# a plotting bug rather than the finding.
|
||||
hk = [r["hack_s"] for r in rs if "hack_s" in r]
|
||||
if hk and np.nanmax([np.nanmax(h) for h in hk]) < 0.02:
|
||||
ax.annotate("hack ≡ 0", (0.04, 0.0), xycoords=("axes fraction", "data"),
|
||||
color=RATE_COLORS["hack_s"], fontsize=8, va="bottom",
|
||||
xytext=(0, 3), textcoords="offset points")
|
||||
ax.set_xlabel("optimizer step")
|
||||
onsets = [s for r in rs if (s := _onset(r["steps"], r["hack_s"])) is not None]
|
||||
if onsets:
|
||||
|
||||
Reference in New Issue
Block a user