我使用 OpenAI Gym 和 Stable-Baselines3 创建了自己的自定义环境。训练完代理后,我尝试使用 stable_baselines3.common.evaluation 中的valuate_policy() 函数来评估策略。但是,该脚本无限期地运行并且永远不会完成。
由于它永远不会完成,我一直在尝试在 CustomEnv() 环境中调试“done”变量,以确保环境always以某种方式结束。除此之外我完全不知所措。
我正在使用的代码如下(为简洁起见,它不包括环境代码):
env = CustomEnv()
env = Monitor(env, log_dir)
model = PPO("MlpPolicy", env, verbose=1, tensorboard_log = log_dir)
timesteps = 5000
for i in range(3):
model.learn(total_timesteps = timesteps, reset_num_timesteps = False, tb_log_name = "PPO")
model.save(f"{models_dir}/car_model_{timesteps * i}")
mean_reward, std_reward = evaluate_policy(model, env, n_eval_episodes=1)
任何有关如何调试此问题的建议或建议都会很棒。
几天前我也遇到了类似的问题。从我的情况来看,我的“评估助手”永远不会停止的原因是:我的自定义环境没有每集的时间步数限制。因此我的评估函数永远运行(因为我的策略很好并且代理没有失败)。
有几个原因
evaluate_policy
可能无法停止:
step()
永远不会回来 done=True
。done
被 evaluate_policy
忽略,因为环境被包装到 Monitor
包装器中,并且包装器无法正确检测终止。对于第一种情况,检查您的环境及其所有包装器是否仍然在某个时刻在
done=True
方法中返回 terminated
(在某些实现中也称为 step()
)。
关于第二种情况。当您使用
stable_baselines3.common.monitor.Monitor
包装器时,evaluate_policy
忽略 done
变量并检查“episode”键,而不是由 Monitor
包装器设置 。当环境“完成”或“截断”时,它会被设置,当像
gym.wrappers.TimeLimit
这样的特殊包装器在环境返回之前
done=True
终止环境时,就会发生这种情况。在这种情况下,TimeLimit
包装器负责返回done
信息。Monitor
和
TimeLimit
包装器的顺序很重要。 Monitor
应在 TimeLimit
之后进行评估以检测时间截断:env = MyEnv()
env = gym.wrappers.TimeLimit(env, max_episode_steps=max_episode_len)
env = Monitor(env, allow_early_resets=True)
逻辑如下。 TimeLimit 在返回
done=True
之前截断 MyEnv,但返回其自己的“完成”以指示截断。 Monitor 从 TimeLimit 获取“done”,设置“episode”键并返回“done”。
evaluate_policy
检查 MyEnv 是否已包装到监视器中,忽略“完成”信息并检查“情节”键。关键就在那里,所以这一集被认为是由 evaluate_policy
完成的。如果 Monitor 和 TimeLimit 是相反的方式,Monitor 将不会得到 done=True
,因为 MyEnv 仍会被 TimeLimit 包装器截断,但在 Monitor 已经执行了检查之后。因此不会设置“剧集”键并且环境将被重置,但
evaluate_policy
不会检测到已完成。根据版本的不同,TimeLimit 还可能以类似 info["TimeLimit.truncated"] = not done
的方式提供有关截断的信息,但
evaluate_policy
方法不直接使用它。