Files

96 lines
3.2 KiB
Python

import gymnasium as gym
import torch
import os
import pickle
from agents.qac import QACAgent
from agents.a2c import A2CAgent
from agents.off_pac import OffPACAgent
from utils import plot_comparison
RESULTS_DIR = 'training_results'
def get_result_path(agent_class, env_name, num_episodes):
os.makedirs(RESULTS_DIR, exist_ok=True)
return os.path.join(RESULTS_DIR, f'{agent_class.__name__}_{env_name}_{num_episodes}.pkl')
def load_or_train(env_name, agent_class, device, num_episodes):
"""检查是否有保存的结果,有则加载,没有则训练并保存。"""
result_path = get_result_path(agent_class, env_name, num_episodes)
if os.path.exists(result_path):
with open(result_path, 'rb') as f:
rewards = pickle.load(f)
print(f"[{agent_class.__name__}] 已找到训练结果文件,直接加载: {result_path}")
return rewards
# 没有结果文件,开始训练
print(f"[{agent_class.__name__}] 未找到结果文件,开始训练...")
rewards = _train_agent(env_name, agent_class, device, num_episodes)
with open(result_path, 'wb') as f:
pickle.dump(rewards, f)
print(f"[{agent_class.__name__}] 训练完成,结果已保存至: {result_path}")
return rewards
def _train_agent(env_name, agent_class, device, num_episodes):
"""实际的训练循环逻辑"""
env = gym.make(env_name)
state_dim = env.observation_space.shape[0] # type: ignore
action_dim = int(env.action_space.n) # type: ignore
agent = agent_class(state_dim, action_dim, device)
rewards_history = []
for episode in range(num_episodes):
state, _ = env.reset()
episode_reward = 0
action = agent.select_action(state)
while True:
next_state, reward, terminated, truncated, _ = env.step(action)
done = terminated or truncated
next_action = agent.select_action(next_state)
agent.update(state, action, reward, next_state, next_action, done)
state = next_state
action = next_action
episode_reward += reward # type: ignore
if done:
break
rewards_history.append(episode_reward)
if (episode + 1) % 100 == 0:
print(f"[{agent_class.__name__}] 回合 {episode+1}/{num_episodes}, 近100回合均分: {sum(rewards_history[-100:])/100:.2f}")
env.close()
return rewards_history
if __name__ == "__main__":
# 检测 GPU
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"正在使用的计算设备: {device}")
ENV_NAME = 'CartPole-v1'
EPISODES = 600
print("\n--- 开始训练 QAC ---")
qac_rewards = load_or_train(ENV_NAME, QACAgent, device, EPISODES)
print("\n--- 开始训练 A2C ---")
a2c_rewards = load_or_train(ENV_NAME, A2CAgent, device, EPISODES)
print("\n--- 开始训练 Off-Policy A2C ---")
off_pac_rewards = load_or_train(ENV_NAME, OffPACAgent, device, EPISODES)
# 将其加入字典一起画图对比
results = {
'QAC': qac_rewards,
'A2C': a2c_rewards,
'Off-Policy A2C': off_pac_rewards
}
plot_comparison(results, window=50, save_path='qac_vs_a2c_gpu.png')