Reinforcement Learning(强化学习)-Gym使用介绍

  • A+
所属分类:深度学习
摘要这一篇作为强化学习的开篇, 会介绍其工具gym的使用. 之后大部分强化学习的实验, 都会基于gym来进行完成. 所以这一篇好好介绍一下gym的使用, 特别是gym配合colab的使用.

简介

这一篇作为Reinforcement Learning的开篇, 主要介绍Gym. 我们之后做强化学习的实验, 都会使用到Gym, 所以还是很有必要好好介绍一下的.

Gym其实就是提供了强化学习需要的环境, 可以创造一些数据集, 用来测试和学习强化学习.

 

Gym初步使用介绍

Gym的安装

安装没什么好说, 直接使用pip进行安装即可.

  1. pip install gym

 

Gym的简单范例

接下来, 我们运行一个Gym的小例子, 开一个CartPole-v0的环境. 注意下面的环境都是来自env基类.

  1. import gym
  2. env = gym.make('CartPole-v0')
  3. env.reset()
  4. for _ in range(1000):
  5.     env.render()
  6.     env.step(env.action_space.sample()) # take a random action
  7. env.close()

我们简单解释一下上面的代码, 首先初始化一个环境, 环境进行渲染, 采取一个action, 这样循环1000次.

如果你在本地命令行运行, 会弹出一个窗口进行模拟, 如下所示.

Reinforcement Learning(强化学习)-Gym使用介绍

但是如果在jupyter notebook或是google Colaboratory就无法直接这样使用, 我会在后面讲如何在colab上运行gym.

 

关于Space的说明

在上面的代码中, 我们可以看到我们每一次的action都是随机进行取值的. 事实上, 每一个环境都有action_space和observation_space.(Every environment comes with an action_space and an observation_space) 我们还是用上面的CartPole-v0来作为例子.

首先我们来看action_spaces, 这个代表可以采取的action的种类, 在CartPole-v0的例子中, 可以采取的action的种类只有两种.

  1. print(env.action_space)
  2. >> Discrete(2)
  3. # 随机选取action
  4. [env.action_space.sample() for i in range(10)]
  5. >> [0, 0, 1, 1, 0, 1, 0, 1, 1, 1]
Reinforcement Learning(强化学习)-Gym使用介绍

接下来我们查看observation_space. 可以查看这个space的shape, 和查看这个space的边界. 简单的看一下下面的示范.

关于这里的high和low的理解, 就是代表四个边界的上界和下界(能取到的最大值和最小值).

Reinforcement Learning(强化学习)-Gym使用介绍

 

对于step的详细说明

上面我们只是每次做随机的action, 为了更好的进行action, 我们需要知道每一步step之后的返回值. 事实上, step会返回四个值. 下面我们一一进行介绍.

  • observation (object): an environment-specific object representing your observation of the environment. For example, pixel data from a camera, joint angles and joint velocities of a robot, or the board state in a board game. (observation可以表示代表当前object的状态, 例如位置信息, 角度信息等)
  • reward (float): amount of reward achieved by the previous action. The scale varies between environments, but the goal is always to increase your total reward. (reward采取这一步action获得的奖励)
  • done (boolean): whether it's time to reset the environment again. Most (but not all) tasks are divided up into well-defined episodes, and done being True indicates the episode has terminated. (For example, perhaps the pole tipped too far, or you lost your last life.) (代表这一轮游戏是否结束, 如果done=True, 表示这一类游戏结束了)
  • info (dict): diagnostic information useful for debugging. It can sometimes be useful for learning (for example, it might contain the raw probabilities behind the environment's last state change). However, official evaluations of your agent are not allowed to use this for learning.

讲了这么多可能有点抽象, 还是上面的例子, 我们实际看一下输出就可以理解了.

  1. import gym
  2. env = gym.make('CartPole-v0')
  3. env.reset()
  4. for _ in range(10):
  5.     env.render()
  6.     observation, reward, done, info = env.step(env.action_space.sample()) # take a random action
  7.     print('observation:{}, reward:{}, done:{}, info:{}'.format(observation, reward, done, info))
  8. env.close()

下面一行, 分别有四个值, 分别是observation, reward, done和info.

Reinforcement Learning(强化学习)-Gym使用介绍

 

上面的就是一个经典的agent-environment循环. agent选择一个action, 环境返回一个observation和reward. 就是如下图所示.(This is just an implementation of the classic "agent-environment loop". Each timestep, the agent chooses an action, and the environment returns an observation and a reward.)

Reinforcement Learning(强化学习)-Gym使用介绍

 

关于render的说明

render其实就相当于一个渲染的引擎, 没有render, 也是可以运行的. 但是render可以为了便于直观显示当前环境中物体的状态, 也是为了便于我们进行代码的调试. 不然只看着一堆数字的observation, 我们也是不知道实际情况怎么样了.

 

Gym进阶使用

环境的状态

当我们注册好了环境之后, 我们可以查看当前环境的所有state的个数与所有action的个数.

Reinforcement Learning(强化学习)-Gym使用介绍

同时, environment还可以返回在当前的state, 采取action, 返回下一个state的种类和概率.

Reinforcement Learning(强化学习)-Gym使用介绍

上面返回的四个值是, state_probability, next_state, reward, terminated.

 

设置从指定状态开始

在使用gym的时候, 有的时候我们需要设置从指定的state开始, 这个可以通过参数environment.s来进行设置, 同时我们要注意的是, environment.state存储的是初始状态(这个可以用dir查询一下, 然后自己尝试, 我在Windy_Gridworld的环境是上面说的这样)

下面我们来看一个例子.

  1. state = environment.reset()
  2. next_state, _, _, _ = environment.step(1)
  3. print(next_state, environment.s)
  4. next_state, _, _, _ = environment.step(1)
  5. print(next_state, environment.s)
  6. environment._render()
  7. # reset到指定state
  8. environment.s= 30
  9. next_state, _, _, _ = environment.step(1)
  10. print(next_state, environment.s)
  11. environment._render()

结果如下图所示, 可以看到第二幅图的时候, 从我们指定的位置30重新开始了.

Reinforcement Learning(强化学习)-Gym使用介绍

 

环境的注册与删除

有的时候, gym中自带的默认的属性可能无法满足我们的需求, 这个时候我们希望可以有自定义修改一些内容, 这个时候就需要对环境进行重新的注册. 我们使用FrozenLake-v0来作为例子说明一下. FrozenLake-v0.

默认情况下, FrozenLake-v0是会出现打滑的, 也就是is_slippery=True, 也就是实际的方向和我们想要的方向不一样. 但是我们不希望有打滑, 于是就需要自己重新注册.

  1. from gym.envs.registration import register

我们通过id的方式使用自带的环境, 并修改参数重新注册, 注意这里使用的id需要与原来的不相同.

  1. register(
  2.     id='FrozenLakeNotSlippery-v0',
  3.     entry_point='gym.envs.toy_text:FrozenLakeEnv',
  4.     kwargs={'map_name' : '4x4', 'is_slippery': False},
  5.     max_episode_steps=30,
  6.     reward_threshold=0.78, # optimum = .8196
  7. )

需要注意的是, 相同的id是不能重复注册的, 否则会出现如下的报错.

  1. Error: Cannot re-register id: FrozenLakeNotSlippery-v0

所以, 当我们需要注册相同的id的时候, 需要先把之前注册的环境进行删除. 我们可以使用下面的命令查看所有已经注册的环境.

  1. gym.envs.registry.env_specs

对环境进行删除, 我们使用del即可.

  1. del gym.envs.registry.env_specs['FrozenLakeNotSlippery-v0']

参考资料:

 

关于jupyter output的删除

在我们测试toy text的时候, 每一次render的内容都会保留在output里面, 但这样看上去不是很方便, 于是我们可以使用clear_output的方式对output进行清除. 下面是一个简单的例子.

  1. from IPython.display import clear_output
  2. for i in range(10):
  3.     clear_output(wait=True)
  4.     print("Hello World!")

参考资料ipython notebook clear cell output in code

 

一个较为完善的例子

有了上面的基础之后, 我们重新修改一开始的CartPole-v0的代码, 我们需要考虑done的状态.

记住, 我们开始的时候需要从reset开始, 他返回一个初始的observation.

  1. observation = env.reset()

于是, 在一般情况下, 我们会将代码写成如下的样子.

  1. import gym
  2. env = gym.make('CartPole-v0')
  3. for i_episode in range(20):
  4.     observation = env.reset()
  5.     for t in range(100):
  6.         env.render()
  7.         print(observation)
  8.         action = env.action_space.sample()
  9.         observation, reward, done, info = env.step(action)
  10.         if done: # 如果结束, 则退出循环
  11.             print("Episode finished after {} timesteps".format(t+1))
  12.             break
  13. env.close()

 

Gym与Colab配合使用

上面讲的都是Gym在本地进行使用, 但是在线上的时候, 特别是Gym配合Colab进行使用的时候, 我们是无法直接使用render的, 因为无法弹出窗口. 这个时候就需要找其他的解决方法.

这一部分完整的代码我都会上传github, 链接地址为: Reinforcement Learning中Gym的使用

安装依赖

首先我们需要安装相应的依赖.

  1. #remove " > /dev/null 2>&1" to see what is going on under the hood
  2. !pip install gym pyvirtualdisplay > /dev/null 2>&1
  3. !apt-get install -y xvfb python-opengl ffmpeg > /dev/null 2>&1

第二组依赖.

  1. !apt-get update > /dev/null 2>&1
  2. !apt-get install cmake > /dev/null 2>&1
  3. !pip install --upgrade setuptools 2>&1
  4. !pip install ez_setup > /dev/null 2>&1
  5. !pip install gym[atari] > /dev/null 2>&1

导入相应的库.

  1. import gym
  2. from gym import logger as gymlogger
  3. from gym.wrappers import Monitor
  4. gymlogger.set_level(40) #error only
  5. import numpy as np
  6. import random
  7. import matplotlib
  8. import matplotlib.pyplot as plt
  9. %matplotlib inline
  10. import math
  11. import glob
  12. import io
  13. import base64
  14. from IPython.display import HTML
  15. from IPython import display as ipythondisplay

使用pyvirtualdisplay进行显示.

  1. from pyvirtualdisplay import Display
  2. display = Display(visible=0, size=(1400, 900))
  3. display.start()

 

使用video recording的方式

这里方法参考自: Rendering OpenAi Gym in Colaboratory

主要的想法就是讲render的过程就存储下来, 最后使用video的方式进行展示. 首先定义一些工具函数.

  1. """
  2. Utility functions to enable video recording of gym environment and displaying it
  3. To enable video, just do "env = wrap_env(env)""
  4. """
  5. def show_video():
  6.   mp4list = glob.glob('video/*.mp4')
  7.   if len(mp4list) > 0:
  8.     mp4 = mp4list[0]
  9.     video = io.open(mp4, 'r+b').read()
  10.     encoded = base64.b64encode(video)
  11.     ipythondisplay.display(HTML(data='''<video alt="test" autoplay 
  12.                 loop controls style="height: 400px;">
  13.                 <source src="data:video/mp4;base64,{0}" type="video/mp4" />
  14.              </video>'''.format(encoded.decode('ascii'))))
  15.   else:
  16.     print("Could not find video")
  17. def wrap_env(env):
  18.   env = Monitor(env, './video', force=True)
  19.   return env

接着就是可视化的例子部分.

  1. env = wrap_env(gym.make("CartPole-v0"))
  2. observation = env.reset()
  3. while True:
  4.     env.render()
  5.     #your agent goes here
  6.     action = env.action_space.sample()
  7.     observation, reward, done, info = env.step(action)
  8.     if done:
  9.       break;
  10. env.close()
  11. show_video()

这样就是使得gym在colab中进行显示了.

 

使用matplotlib进行显示

这里我们使用另外一种方式, 我们将每一帧的画面, 使用matplotlib绘制出来, 接着间隔固定时间进行清除, 最后就可以看上去是动态的图像了, 我们还是看一个例子.

就直接参考下面的代码, 我已经写上了详细的注释了, 同样, 可以直接去github上查看代码, 链接地址为: Reinforcement Learning中Gym的使用.

  1. env = gym.make('CartPole-v0') # 初始化场景
  2. env.reset() # 初始状态
  3. env.render(mode='rgb_array')
  4. t = 0
  5. # 随便动一步(初始状态)
  6. action = env.action_space.sample()
  7. state, _, done, _ = env.step(action)
  8. env.render(mode='rgb_array')
  9. # 绘图
  10. plt.figure()
  11. plt.clf()
  12. plt.title('Example extracted screen')
  13. while True:
  14.     action = env.action_space.sample()
  15.     # 往后走一步
  16.     state, _, done, _ = env.step(action)
  17.     # 生成走后的场景
  18.     current_screen = env.render(mode='rgb_array') # 返回现在的图像, 用于可视化
  19.     # 绘制画面
  20.     plt.pause(0.7)  # pause a bit so that plots are updated
  21.     ipythondisplay.clear_output(wait=True)
  22.     ipythondisplay.display(plt.gcf())
  23.     plt.title('Action: {}'.format(action))
  24.     plt.imshow(current_screen, interpolation='none')
  25.     t = t + 1
  26.     if done:
  27.         break
  28.     if t>100:
  29.         break
  30. plt.show()
  31. env.close()
  32. print(t)

最终的效果如下图所示:

Reinforcement Learning(强化学习)-Gym使用介绍
  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: