pusher-v5-ppo / evaluate.py
hwihwalab's picture
feat: deploy Pusher-v5 PPO model, telemetry cockpit, and video gallery
f8364f0 verified
Raw
History Blame Contribute Delete
4.24 kB
"""
evaluate.py
ํ•™์Šต ์™„๋ฃŒ๋œ Pusher-v5 PPO ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ •๋ฐ€ ํ‰๊ฐ€ํ•˜๊ณ  ๊ณ ํ™”์งˆ ๋น„๋””์˜ค/GIF๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
"""
import os
import argparse
import numpy as np
import gymnasium as gym
from stable_baselines3 import PPO
import visualizer
def evaluate_model(
model_path: str,
episodes: int = 5,
output_dir: str = "./eval_results",
seed: int = 100,
fps: int = 30,
):
"""
์ €์žฅ๋œ PPO ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์—ํ”ผ์†Œ๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์‹œ๊ฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
"""
os.makedirs(output_dir, exist_ok=True)
print("=" * 65)
print(f" [Evaluation] ๋ชจ๋ธ ๋กœ๋“œ ์ค‘: {model_path}")
print(f" - ํ‰๊ฐ€ ์—ํ”ผ์†Œ๋“œ ์ˆ˜: {episodes}")
print(f" - ์ถœ๋ ฅ ๋””๋ ‰ํ† ๋ฆฌ : {output_dir}")
print("=" * 65)
# ํ™˜๊ฒฝ ๋ฐ ๋ชจ๋ธ ๋กœ๋“œ
env = gym.make("Pusher-v5", render_mode="rgb_array")
model = PPO.load(model_path, env=env)
all_rewards = []
all_dists_goal = []
all_dists_arm = []
for ep in range(episodes):
obs, info = env.reset(seed=seed + ep)
done = False
ep_reward = 0.0
ep_step = 0
frames = []
final_dist_goal = 0.0
final_dist_arm = 0.0
while not done:
action, _ = model.predict(obs, deterministic=True)
next_obs, reward, terminated, truncated, step_info = env.step(action)
ep_reward += float(reward)
ep_step += 1
done = terminated or truncated
reward_dist = step_info.get("reward_dist", 0.0)
reward_near = step_info.get("reward_near", 0.0)
final_dist_goal = abs(reward_dist) / 1.25 if reward_dist <= 0 else reward_dist
final_dist_arm = abs(reward_near) if reward_near <= 0 else reward_near
raw_frame = env.render()
if raw_frame is not None:
hud_frame = visualizer.draw_hud_on_frame(
frame=raw_frame,
timestep=-1,
episode=ep + 1,
step=ep_step,
step_reward=float(reward),
total_reward=ep_reward,
reward_dist=reward_dist,
reward_near=reward_near,
actions=action,
tag=f"Eval Ep {ep+1}",
)
frames.append(hud_frame)
obs = next_obs
all_rewards.append(ep_reward)
all_dists_goal.append(final_dist_goal)
all_dists_arm.append(final_dist_arm)
# ์—ํ”ผ์†Œ๋“œ๋ณ„ ๋น„๋””์˜ค/GIF ์ €์žฅ
out_base = os.path.join(output_dir, f"eval_episode_{ep+1}")
gif_path, mp4_path = visualizer.save_video_and_gif(frames, out_base, fps=fps)
print(f"Episode {ep+1:02d} | Return: {ep_reward:+.2f} | Final Goal Dist: {final_dist_goal:.3f}m | Arm Dist: {final_dist_arm:.3f}m")
print(f" -> ๋น„๋””์˜ค: {mp4_path} | GIF: {gif_path}")
env.close()
print("\n" + "=" * 65)
print(" [Evaluation Summary]")
print(f" - ํ‰๊ท  ๋ณด์ƒ (Mean Return) : {np.mean(all_rewards):+.2f} ยฑ {np.std(all_rewards):.2f}")
print(f" - ํ‰๊ท  ๋ชฉํ‘œ ๊ฑฐ๋ฆฌ (Mean Goal Dist) : {np.mean(all_dists_goal):.3f}m")
print(f" - ํ‰๊ท  ํŒ”-๋ฌผ์ฒด ๊ฑฐ๋ฆฌ (Mean Arm Dist): {np.mean(all_dists_arm):.3f}m")
print("=" * 65)
def main():
parser = argparse.ArgumentParser(description="Pusher-v5 PPO ๋ชจ๋ธ ๋…๋ฆฝ ํ‰๊ฐ€ ๋ฐ ๋น„๋””์˜ค ์ƒ์„ฑ")
parser.add_argument("--model_path", type=str, default="./results/ppo_pusher.zip", help="ํ‰๊ฐ€ํ•  ๋ชจ๋ธ ํŒŒ์ผ ๊ฒฝ๋กœ (.zip)")
parser.add_argument("--episodes", type=int, default=3, help="ํ‰๊ฐ€ํ•  ์—ํ”ผ์†Œ๋“œ ์ˆ˜ (๊ธฐ๋ณธ: 3)")
parser.add_argument("--output_dir", type=str, default="./eval_results", help="ํ‰๊ฐ€ ๊ฒฐ๊ณผ๋ฌผ ์ €์žฅ ๋””๋ ‰ํ† ๋ฆฌ")
parser.add_argument("--seed", type=int, default=100, help="ํ‰๊ฐ€ ๋žœ๋ค ์‹œ๋“œ")
parser.add_argument("--fps", type=int, default=30, help="๋น„๋””์˜ค ์žฌ์ƒ FPS")
args = parser.parse_args()
evaluate_model(
model_path=args.model_path,
episodes=args.episodes,
output_dir=args.output_dir,
seed=args.seed,
fps=args.fps,
)
if __name__ == "__main__":
main()