Download plots.py from dummy033485/multi-agent-rl-navigation: direct link, hf CLI and curl.
- Browser
- Download file 6.06 kB
-
https://huggingface.co/dummy033485/multi-agent-rl-navigation/resolve/main/plots.py
- Command line
-
hf download hf://dummy033485/multi-agent-rl-navigation/plots.py
-
curl -L -o plots.py https://huggingface.co/dummy033485/multi-agent-rl-navigation/resolve/main/plots.py
6.06 kB
| """Plots from results.json + live rollouts of the trained policy. | |
| Outputs (plots/): | |
| trap_trajectories.png - one wall-trap layout, RL vs classical | |
| four_agent.png - one 4-agent layout, RL vs classical (2 panels) | |
| clean_comparison.png - bar chart: clean success / collision, RL vs | |
| classical, single-agent and 4-agent | |
| training_curve.png - training success/collision over iterations | |
| """ | |
| import argparse | |
| import json | |
| import matplotlib | |
| matplotlib.use("Agg") | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| import torch | |
| from sim import generate_layout, NavSim | |
| from policies import ActorCritic, classical_action, rl_action | |
| def draw(ax, layout, traj, goals, title): | |
| ax.set_xlim(0, 12); ax.set_ylim(0, 12) | |
| ax.set_aspect("equal"); ax.set_title(title, fontsize=10) | |
| ax.set_xlabel("x"); ax.set_ylabel("y") | |
| for (cx, cy, r) in layout["circles"]: | |
| ax.add_patch(plt.Circle((cx, cy), r, color="0.7", zorder=1)) | |
| ax.add_patch(plt.Circle((cx, cy), r, fill=False, color="k", lw=0.8, zorder=2)) | |
| for (x1, y1, x2, y2) in layout["segments"]: | |
| ax.plot([x1, x2], [y1, y2], color="k", lw=4, solid_capstyle="butt", zorder=2) | |
| colors = ["#1f77b4", "#d62728", "#2ca02c", "#9467bd"] | |
| for i, tr in enumerate(traj): | |
| tr = np.array(tr) | |
| ax.plot(tr[:, 0], tr[:, 1], color=colors[i % 4], lw=1.5, zorder=3) | |
| ax.scatter([tr[0, 0]], [tr[0, 1]], marker="o", s=45, color=colors[i % 4], zorder=4) | |
| ax.scatter([goals[i, 0]], [goals[i, 1]], marker="*", s=160, color=colors[i % 4], | |
| edgecolor="k", linewidth=0.5, zorder=4) | |
| ax.add_patch(plt.Rectangle((0, 0), 12, 12, fill=False, color="k", lw=1.2)) | |
| def rollout(policy, net, layout, n_agents): | |
| sim = NavSim(n_agents, seed=0) | |
| obs = sim.reset(layout) | |
| while True: | |
| act = classical_action(obs) if policy == "classical" else rl_action(net, obs, deterministic=True) | |
| obs, _, done, _ = sim.step(act) | |
| if done: | |
| break | |
| return sim.traj, sim.success, sim.collision | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--weights", default="ppo_policy.pt") | |
| ap.add_argument("--results", default="results.json") | |
| ap.add_argument("--curve", default="training_curve.csv") | |
| ap.add_argument("--outdir", default="plots") | |
| args = ap.parse_args() | |
| import os | |
| os.makedirs(args.outdir, exist_ok=True) | |
| net = ActorCritic() | |
| net.load_state_dict(torch.load(args.weights, map_location="cpu", weights_only=True)) | |
| net.eval() | |
| # trap layout: seed 1001 (second single-agent layout, trap) | |
| rng = np.random.default_rng(1001) | |
| trap_layout = generate_layout(rng, 1, trap=True) | |
| fig, axes = plt.subplots(1, 2, figsize=(10, 5)) | |
| for ax, policy in zip(axes, ["classical", "rl"]): | |
| traj, succ, coll = rollout(policy, net, trap_layout, 1) | |
| draw(ax, trap_layout, traj, trap_layout["goals"], | |
| f"{policy}: {'SUCCESS' if succ[0] else 'COLLISION' if coll[0] else 'TIMEOUT'}") | |
| fig.tight_layout() | |
| fig.savefig(f"{args.outdir}/trap_trajectories.png", dpi=150) | |
| plt.close(fig) | |
| # 4-agent layout: seed 2001 (second 4-agent layout, trap) | |
| rng = np.random.default_rng(2001) | |
| lay4 = generate_layout(rng, 4, trap=True) | |
| fig, axes = plt.subplots(1, 2, figsize=(10, 5)) | |
| for ax, policy in zip(axes, ["classical", "rl"]): | |
| traj, succ, coll = rollout(policy, net, lay4, 4) | |
| draw(ax, lay4, traj, lay4["goals"], | |
| f"{policy}: {int(succ.sum())}/4 success, {int(coll.sum())} collisions") | |
| fig.tight_layout() | |
| fig.savefig(f"{args.outdir}/four_agent.png", dpi=150) | |
| plt.close(fig) | |
| # bar chart from results.json | |
| with open(args.results) as f: | |
| res = json.load(f) | |
| clean = res["conditions"]["clean"] | |
| labels = ["1-agent\nclassical", "1-agent\nRL", "4-agent\nclassical", "4-agent\nRL"] | |
| succ = [clean["1_agent"]["classical"]["success_rate"], | |
| clean["1_agent"]["rl"]["success_rate"], | |
| clean["4_agent"]["classical"]["success_rate"], | |
| clean["4_agent"]["rl"]["success_rate"]] | |
| coll = [clean["1_agent"]["classical"]["collision_rate"], | |
| clean["1_agent"]["rl"]["collision_rate"], | |
| clean["4_agent"]["classical"]["collision_rate"], | |
| clean["4_agent"]["rl"]["collision_rate"]] | |
| x = np.arange(len(labels)); w = 0.35 | |
| fig, ax = plt.subplots(figsize=(8, 4.5)) | |
| ax.bar(x - w / 2, succ, w, label="success rate") | |
| ax.bar(x + w / 2, coll, w, label="collision rate") | |
| ax.set_xticks(x); ax.set_xticklabels(labels) | |
| ax.set_ylim(0, 1.05); ax.set_ylabel("rate"); ax.set_title("Clean evaluation: RL vs classical") | |
| ax.legend() | |
| for i, v in enumerate(succ): | |
| ax.text(i - w / 2, v + 0.02, f"{v:.2f}", ha="center", fontsize=9) | |
| for i, v in enumerate(coll): | |
| ax.text(i + w / 2, v + 0.02, f"{v:.2f}", ha="center", fontsize=9) | |
| fig.tight_layout() | |
| fig.savefig(f"{args.outdir}/clean_comparison.png", dpi=150) | |
| plt.close(fig) | |
| # training curve (concatenated curves passed in --curve if present) | |
| try: | |
| import csv | |
| iters, s, c = [], [], [] | |
| with open(args.curve) as f: | |
| for row in csv.DictReader(f): | |
| if row["success_rate_finished"] and row["success_rate_finished"] != "nan": | |
| iters.append(int(row["iteration"])); s.append(float(row["success_rate_finished"])) | |
| c.append(float(row["collision_rate_finished"])) | |
| fig, ax = plt.subplots(figsize=(8, 4)) | |
| ax.plot(iters, s, label="training success rate (finished episodes)") | |
| ax.plot(iters, c, label="training collision rate") | |
| ax.set_xlabel("iteration"); ax.set_ylabel("rate"); ax.legend() | |
| ax.set_title("PPO training curve (last training run only)") | |
| fig.tight_layout() | |
| fig.savefig(f"{args.outdir}/training_curve.png", dpi=150) | |
| plt.close(fig) | |
| except FileNotFoundError: | |
| pass | |
| print("plots written to", args.outdir) | |
| if __name__ == "__main__": | |
| main() | |