Download scripts/plot_results.py from ChatterjeeLab/DooABLe: direct link, hf CLI and curl.
- Browser
- Download file 4.37 kB
-
https://huggingface.co/ChatterjeeLab/DooABLe/resolve/main/scripts/plot_results.py
- Command line
-
hf download hf://ChatterjeeLab/DooABLe/scripts/plot_results.py
-
curl -L -o plot_results.py https://huggingface.co/ChatterjeeLab/DooABLe/resolve/main/scripts/plot_results.py
4.37 kB
| """Create vector plots and a LaTeX table from recorded benchmark measurements.""" | |
| import argparse | |
| from pathlib import Path | |
| import json | |
| import matplotlib | |
| matplotlib.use("Agg") | |
| from matplotlib import pyplot as plt, font_manager | |
| import pandas as pd | |
| ROOT = Path(__file__).resolve().parents[1] | |
| COLORS = ["#4E95C0", "#245778", "#A7D3EE", "#718594", "#7EB4D5", "#364C5B", "#D7EAF6"] | |
| LABELS = { | |
| "dooable": "DooABLe", | |
| "tb_uniform": "TB, uniform backward", | |
| "tb_exact": "TB, exact backward", | |
| "uniform": "Uniform executable", | |
| "reference_tilt": "Reference tilt", | |
| "exact": "Exact joint law", | |
| "zero_cost": "Zero route cost", | |
| "duplicate_endpoints": "Duplicate endpoints", | |
| "unnormalized": "Unnormalized backward", | |
| } | |
| def main(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--run", required=True) | |
| parser.add_argument("--output") | |
| args = parser.parse_args() | |
| run = Path(args.run) | |
| out = Path(args.output) if args.output else run / "plots" | |
| out.mkdir(parents=True, exist_ok=True) | |
| font = ROOT / "assets/fonts/Ubuntu-Regular.ttf" | |
| if not font.exists(): | |
| font = ROOT / "paper/figures/fonts/Ubuntu-Regular.ttf" | |
| font_manager.fontManager.addfont(str(font)) | |
| plt.rcParams.update( | |
| { | |
| "font.family": "Ubuntu", | |
| "font.size": 9, | |
| "mathtext.fontset": "cm", | |
| "pdf.fonttype": 42, | |
| "axes.spines.top": False, | |
| "axes.spines.right": False, | |
| } | |
| ) | |
| df = pd.read_csv(run / "metrics.csv") | |
| methods = list(dict.fromkeys(df.method)) | |
| fig, axes = plt.subplots(1, 3, figsize=(10, 3.2)) | |
| specifications = [ | |
| ("endpoint_tv", "Endpoint TV"), | |
| ("conditional_free_energy_gap", "Conditional gap (cost units)"), | |
| ("mean_cost", "Mean execution cost"), | |
| ] | |
| for ax, (metric, label) in zip(axes, specifications): | |
| summary = df.groupby("method")[metric].agg(["mean", "sem"]).reindex(methods) | |
| ax.bar( | |
| range(len(methods)), | |
| summary["mean"], | |
| yerr=summary["sem"].fillna(0), | |
| color=COLORS[: len(methods)], | |
| capsize=2, | |
| ) | |
| ax.set_ylabel(label) | |
| ax.set_xticks( | |
| range(len(methods)), [LABELS[x] for x in methods], rotation=40, ha="right" | |
| ) | |
| fig.tight_layout() | |
| fig.savefig(out / "benchmark.pdf") | |
| fig.savefig(out / "benchmark.png", dpi=220) | |
| plt.close(fig) | |
| histories = [] | |
| for path in sorted(run.glob("*_seed*/training.json")): | |
| frame = pd.read_json(path) | |
| frame["method"] = path.parent.name.rsplit("_seed", 1)[0] | |
| frame["seed"] = int(path.parent.name.rsplit("_seed", 1)[1]) | |
| histories.append(frame) | |
| if histories: | |
| history = pd.concat(histories) | |
| fig, ax = plt.subplots(figsize=(5.3, 3.1)) | |
| for color, (method, group) in zip(COLORS, history.groupby("method")): | |
| stats = group.groupby("step").endpoint_tv.agg(["mean", "sem"]) | |
| x = stats.index.to_numpy() | |
| mean = stats["mean"].to_numpy() | |
| sem = stats["sem"].fillna(0).to_numpy() | |
| ax.plot(x, mean, label=LABELS[method], color=color) | |
| ax.fill_between(x, mean - sem, mean + sem, color=color, alpha=0.15) | |
| ax.set_xlabel("Training updates") | |
| ax.set_ylabel("Endpoint TV") | |
| ax.legend(frameon=False) | |
| fig.tight_layout() | |
| fig.savefig(out / "training.pdf") | |
| fig.savefig(out / "training.png", dpi=220) | |
| plt.close(fig) | |
| summary = df.groupby("method")[[x[0] for x in specifications]].agg(["mean", "sem"]) | |
| lines = [ | |
| "\\begin{tabular}{lccc}", | |
| "\\toprule", | |
| "Method & TV & Conditional gap & Mean cost \\\\", | |
| "\\midrule", | |
| ] | |
| for method in methods: | |
| cells = [] | |
| for metric, _ in specifications: | |
| value = summary.loc[method, (metric, "mean")] | |
| sem = summary.loc[method, (metric, "sem")] | |
| cells.append( | |
| f"${value:.4g}$" if pd.isna(sem) else f"${value:.4g} \\pm {sem:.2g}$" | |
| ) | |
| lines.append(LABELS[method] + " & " + " & ".join(cells) + " \\\\") | |
| lines.extend(["\\bottomrule", "\\end{tabular}"]) | |
| (out / "measurements.tex").write_text("\n".join(lines) + "\n") | |
| print(json.dumps({"rows": len(df), "plots": str(out)})) | |
| if __name__ == "__main__": | |
| main() | |