关于gym包升级到0.26.2版本后炼丹炉测试代码的修改

前两天电脑有问题,重装了系统。就有了关于安装了更新后的软件包跑环境测试代码遇到的问题。
本文包版本分别为——gym version:0.26.2,pygame version:2.1.2

注意:
很多同学说老测试代码跑不出来的,是因为gym升级了!gym库0.26.0及之后的版本和之前版本的代码是不兼容的!建议要么用命令:pip install gym==0.25.2安装老版本gym(这里的0.25.0版本只是举个例子,当然也可以用其他老版本),要么尝试一下下文中的代码。

A.测试代码1

由于十月份电脑有些问题重装了一边系统,因此又开始搭环境跑测试代码,果不其然,各种问题出来了。把pycharm、anaconda装好后,rl环境创建好后,并在rl环境中成功安装好gym、pygame、pytorch包以为能成功进入炼丹炉,就拿了之前的测试代码1跑了一下:

import gym
env = gym.make('MountainCar-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
    if done:
        print("Episode finished after {} timesteps".format(t+1))
        break
env.close()

然鹅,出错了:
报错信息
细看是两个错误提示:

提示1

WARN: You are calling render method without specifying any render mode. You can specify the render_mode at initialization, e.g. gym("MountainCar-v0", render_mode="rgb_array") gym.logger.warn(

大概意思是我们调用render method的时候没有明确指定render mode,我们应当在初始化的时候就指出render_mode,例如gym(“MountainCar-v0”, render_mode=“rgb_array”)。
按照他的提示修改,在原代码

env = gym.make('MountainCar-v0')

处修改为:

env = gym.make('MountainCar-v0', render_mode = "human")

再次运行发现小车上山的pygame界面一闪而过。以上关于render_mode的这个错误,我想可能是由于gym库的版本更新以后,在定义环境时需要在环境名后具体指出render_mode=…,注意必须指出具体的render_mode(渲染模式),否则pygame的画面直接就不显示了,所以在用原来的测试代码是跑不出pygame画面的。

提示2

错误提示2

这个错误提示的意思是:
值错误:接收返回值不符(这个问题参考的这个链接)
我理解的意思就是说环境里给我们的接受值和我们设置接受变量的数量之间无法对应起来(比如环境给你5个值,你却只设置了4个或更少的变量去接受,这肯定是不对的)。现在我们来查看env.step(action)到底给了我们几个value。利用下列代码来查看:

print(len(env.step(action)))

运行后可以看到“运行”里打印出了5,也就是说给了5个值需要用五个容器(变量)来接收。

其实关于这5个返回值,gym在Gym Documentation的首页就已经给出了(我用鼠标选中的那行代码):
Gym Documentation首页
即:

observation, reward, terminated, truncated, info = env.step(action)

observationrewardterminatedtruncatedinfo就是env.step()返回给我们的5个值。

我们在实验中具体看一下这5个值具体长什么样子(注意下面我用的是MountainCar-v0环境):
PyCharm中的Python Console
可以看到最后一行的输出:

(array([-0.57811695, -0.00059736], dtype=float32), -1.0, False, False, {})

其中:

  • (array([-0.57811695, -0.00059736], dtype=float32)是智能体观测到的环境状态observation
  • -1.0是智能体执行动作后获得的奖励reward
  • 第一个Falseterminated表示当前状态是否为终止状态(terminal state),即智能体是否已完成任务或失败退出;
  • 第二个Falsetruncated表示当前交互是否被截断(truncated),即智能体是否在一个时间步内完成了任务,或者达到了最大交互步数而被中断;
  • {}是个空字典表示额外信息info

如果你只需要其中的一部分变量,你可以使用下划线 _ 来代替不需要的变量名,例如可以把原代码:

observation, reward, done, info = env.step(action)

改为:

observation, reward, _ , done, info = env.step(action)

运行效果:
运行效果

附上修改后的测试代码1

import gym
env = gym.make('MountainCar-v0', render_mode = 'human')
for i_episode in range(10):
    observation = env.reset()
    for t in range(100):
        env.render()
        print(observation)
        action = env.action_space.sample()
        observation, reward, done, info, _ = env.step(action)
    if done:
        print("Episode finished after {} timesteps".format(t+1))
        break
env.close()

关于render_mode,我在core.py文件中看到有如下说明:

render_mode的说明

B.测试代码2

跑的另一个测试代码2也是有2个提示。
原测试代码2如下:

import gym
env = gym.make('CartPole-v0')
for episode in range(10):
  env.reset()
  print("Episode finished after {} timesteps".format(episode))
  for _ in range(100):
    env.render()
    env.step(env.action_space.sample())
env.close()

结果有print的结果,没出现pygame的界面,按照提示作出修改:
错误提示

提示1

他说You are calling render method without specifying any render mode. You can specify the render_mode at initialization, e.g. gym("MountainCar-v0", render_mode="rgb_array")
大概意思是我们调用render method的时候没有明确指定render mode,我们应当在初始化的时候就指出render_mode,例如gym("MountainCar-v0", render_mode="rgb_array")
按照他的提示修改,在原代码

env = gym.make('CartPole-v0')

处修改为:

env = gym.make('CartPole-v0', render_mode = "human")

现在运行程序,就可以看到车杆平衡的pygame界面了。

提示2

然而,还有一个问题:
错误提示2

大概意思是说,即使terminated = 1了我依然还在调用step函数,terminated = 1的时候应该接着的是reset函数。我理解的意思是当我们完成一个episode(序列/情节/轨迹)后,环境会告诉我们训练应当终止了就会返回给我们terminated = 1这个信号,并且希望我们通过reset函数重置智能体的状态,让他继续探寻下一个episode。但是这里有个疑问:这条警告有时出现有时不出现,目前原因不明。比如我加了一句代码:

print("1 step")

就没有这样的警告:
在这里插入图片描述

有的时候去掉也没有,有时又会出现。总之运行效果如下图:
运行效果

附上修改后的测试代码2

import gym
env = gym.make('CartPole-v1', render_mode = "human")
for episode in range(10):
  env.reset()
  print("Episode finished after {} timesteps".format(episode))
  for _ in range(100):
    env.render()
    env.step(env.action_space.sample())
env.close()
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐