| import argparse |
| import json |
| from pathlib import Path |
|
|
| import matplotlib.pyplot as plt |
|
|
| from trainer_utils import get_best_checkpoint |
|
|
|
|
| def parse_args(): |
| parser = argparse.ArgumentParser(description="Plot learning_curve.jsonl") |
| parser.add_argument("--run-dir", required=True) |
| return parser.parse_args() |
|
|
|
|
| def load_curve(path): |
| rows = [] |
| with Path(path).open(encoding="utf-8") as file: |
| for line in file: |
| rows.append(json.loads(line)) |
|
|
| by_step = {} |
| for row in rows: |
| step = row.get("step") |
| if step is not None: |
| by_step[step] = {**by_step.get(step, {}), **row} |
| return [by_step[step] for step in sorted(by_step)] |
|
|
|
|
| def plot_metric(axis, rows, key, label, color): |
| selected = [row for row in rows if key in row and row.get("step") is not None] |
| if selected: |
| axis.plot( |
| [row["step"] for row in selected], |
| [row[key] for row in selected], |
| label=label, |
| color=color, |
| ) |
| axis.set_ylabel(label) |
| axis.legend() |
| axis.grid(True) |
|
|
|
|
| def main(): |
| args = parse_args() |
| run_dir = Path(args.run_dir) |
| rows = load_curve(run_dir / "learning_curve.jsonl") |
| _, best_step = get_best_checkpoint(run_dir) |
|
|
| fig, axes = plt.subplots(4, 1, figsize=(10, 12), sharex=True) |
| plot_metric(axes[0], rows, "loss", "train_loss", "tab:blue") |
| plot_metric(axes[1], rows, "eval_accuracy", "eval_accuracy", "tab:orange") |
| plot_metric(axes[2], rows, "eval_precision", "eval_precision", "tab:green") |
| plot_metric(axes[3], rows, "eval_f1", "eval_f1", "tab:red") |
|
|
| if best_step is not None: |
| for axis in axes: |
| axis.axvline(best_step, linestyle="--", color="black", label="best") |
|
|
| axes[-1].set_xlabel("step") |
| fig.tight_layout() |
| out_path = run_dir / "learning_curve.png" |
| fig.savefig(out_path, dpi=150) |
| print("saved:", out_path) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|