Kr0issant
training loop v1
dec56a6
Raw
History Blame Contribute Delete
4.82 kB
"""Plot benchmark summaries for hackathon evidence artifacts."""
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
def plot_benchmark_file(input_path: Path | str, output_dir: Path | str) -> list[Path]:
payload = json.loads(Path(input_path).read_text(encoding="utf-8"))
return plot_benchmark_payload(payload, output_dir)
def plot_benchmark_payload(payload: dict[str, Any], output_dir: Path | str) -> list[Path]:
import matplotlib.pyplot as plt
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
policies = [policy["policy"] for policy in payload["policies"]]
mean_returns = [
policy["summary"]["mean_episode_return"]
for policy in payload["policies"]
]
survival_rounds = [
policy["summary"]["mean_survival_rounds"]
for policy in payload["policies"]
]
written_paths = [
_write_bar_chart(
plt=plt,
labels=policies,
values=mean_returns,
title="Mean Episode Return by Baseline",
ylabel="Mean episode return",
output_path=output_path / "baseline_mean_episode_return.png",
),
_write_bar_chart(
plt=plt,
labels=policies,
values=survival_rounds,
title="Survival Rounds by Baseline",
ylabel="Mean survival rounds",
output_path=output_path / "baseline_survival_rounds.png",
),
]
plt.close("all")
return written_paths
def plot_policy_comparison(
payload: dict[str, Any],
output_dir: Path | str,
*,
filename: str = "policy_comparison.png",
) -> Path:
"""Bar chart of mean episode return per policy, highlighting LLM variants.
Used for the "before vs after" GRPO evidence in the README. The trained
parliamentary LoRA bar is colour-coded so reviewers can spot the lift over
the untrained base model and rule-based baselines at a glance.
"""
import matplotlib.pyplot as plt
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
policies = [policy["policy"] for policy in payload["policies"]]
mean_returns = [
policy["summary"]["mean_episode_return"]
for policy in payload["policies"]
]
colors = [_policy_color(name) for name in policies]
figure, axis = plt.subplots(figsize=(9, 5))
axis.bar(policies, mean_returns, color=colors)
axis.set_title("Mean Episode Return by Policy (rule-based vs LLM)")
axis.set_xlabel("Policy")
axis.set_ylabel("Mean episode return")
axis.tick_params(axis="x", labelrotation=25)
axis.grid(axis="y", alpha=0.25)
figure.tight_layout()
written = output_path / filename
figure.savefig(written, dpi=160)
plt.close(figure)
return written
def plot_survival_rounds(
payload: dict[str, Any],
output_dir: Path | str,
*,
filename: str = "survival_rounds.png",
) -> Path:
"""Per-policy survival distribution box-plot from raw episode metrics."""
import matplotlib.pyplot as plt
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
labels: list[str] = []
distributions: list[list[float]] = []
for policy in payload["policies"]:
survivals = [
float(episode["rounds_survived"])
for episode in policy.get("episodes", [])
]
if not survivals:
survivals = [float(policy["summary"]["mean_survival_rounds"])]
labels.append(policy["policy"])
distributions.append(survivals)
figure, axis = plt.subplots(figsize=(9, 5))
axis.boxplot(distributions, tick_labels=labels, showmeans=True)
axis.set_title("Survival Rounds Distribution by Policy")
axis.set_xlabel("Policy")
axis.set_ylabel("Rounds survived")
axis.tick_params(axis="x", labelrotation=25)
axis.grid(axis="y", alpha=0.25)
figure.tight_layout()
written = output_path / filename
figure.savefig(written, dpi=160)
plt.close(figure)
return written
def _policy_color(name: str) -> str:
if name == "parliamentary_grpo":
return "#E45756"
if name == "parliamentary_base":
return "#F58518"
return "#4C78A8"
def _write_bar_chart(
*,
plt: Any,
labels: list[str],
values: list[float],
title: str,
ylabel: str,
output_path: Path,
) -> Path:
figure, axis = plt.subplots(figsize=(8, 4.5))
axis.bar(labels, values, color="#4C78A8")
axis.set_title(title)
axis.set_xlabel("Policy baseline")
axis.set_ylabel(ylabel)
axis.tick_params(axis="x", labelrotation=25)
axis.grid(axis="y", alpha=0.25)
figure.tight_layout()
figure.savefig(output_path, dpi=160)
plt.close(figure)
return output_path