78强化学习基础算法及实践--OpenAI Gym 环境介绍及使用

OpenAI Gym 环境介绍及使用

前面的强化学习介绍实验中,我们给出了如下所示的强化学习流程图。可以很清楚看到,环境是强化学习的基础,智能体在强化学习的过程中始终和环境发生着交互,并从环境中获得奖励。这也是强化学习区别于监督学习或非监督学习的重要特点。


image.png

正是因为强化学习需要环境这个先决条件,当我们想要调试或对比强化学习算法时都需要先搭建环境(比如先设计并建造迷宫,确定奖励等),而这往往是一个复杂的过程,且需要掌握更多的技术才能得以实现。所以,Q-Learning 学习时只能使用文字迷宫游戏。
如今,有了 OpenAI 的 Gym 环境,这将不再是一件麻烦的事情,尤其是对于初学者而言,可以很快地上手强化学习算法,并在有趣的游戏环境中实验。

Gym 环境安装

首先,我们来说一下 Gym 环境的安装。受限于 Notebook 的限制,蓝桥云课在线实验只能使用 Gym 中的部分环境。如果想要尝试全部的环境,则最好是在桌面环境中使用。
目前,Gym 官方仅支持 Linux 或使用 UNIX 内核的操作系统,也就是 Ubuntu 或者 macOS 都可以使用。官方并不支持 Windows,但有一些博客文章也给出了解决方案。下面,我们以在 Ubuntu 中安装 Gym 举例。
Gym 的安装大致分为 3 步,首先是更新 apt 包管理工具:

sudo apt-get update

然后,安装相应的依赖包:

sudo apt-get install -y python-numpy python-dev cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev python-opengl libboost-all-dev libsdl2-dev swig

最后通过 pip 安装 gym 模块:

sudo pip install gym

你可以使用 gym[all] 安装 Gym 提供的全部环境,这需要你单独安装 MuJoCo 模块,具体请参考 官方文档
目前,我们的线上环境已经安装了完整的 Gym 环境。

Gym 环境使用

Gym 提供的全部环境中主要包含下面几大类:
Atari:几十种小游戏,例如打方块、乒乓球等。
Box2D:二维环境下的连续任务,例如开小车、机器人行走等。
Classic control:经典的控制任务,例如简单机械臂控制或者小车爬坡任务。
MuJoCo:三维环境中的连续任务,例如小人在地板上行走等。【需要单独付费安装】
Robotics:机械臂模拟任务。
Toy text:非常简单的文字游戏。

关于这些环境的详细信息,可以通过 此链接查看

冰面飞盘游戏示例

接下来,我们通过一个叫 FrozenLake-v0 的文字游戏入门 Gym 的使用。FrozenLake-v0 是一个在冰面上捡飞盘的游戏,默认为 4x4 的网格。例如:
[ SFFF FHFH FFFH HFFG]
其中,S 表示起点,G 表示分盘所在的目标点,F 表示安全的冰冻表面,H 表示冰窟窿。Agent 每次从 S 出发,掉入冰窟窿游戏结束,成功捡到飞盘将收获奖励 1。另外,冰面很滑,所以不一定会按照预想的方向移动。
首先,我们需要加载环境,方法非常简单:

import gym
import warnings
warnings.filterwarnings('ignore')

env = gym.make('FrozenLake-v0')  # 加载相应环境
env.action_space  # 查看该环境中可用 action 数量

上面输出的 Discrete(4),即代表可以有 4 个动作,你可以想到是上、下、左、右。现在可以启动环境了。

env.reset()  # 运行前一般需要先重置环境
env.render()  # 启动渲染环境

此时如果 Agent 采取一个随机行动,环境就会反馈奖励并进入下一个状态。

action = env.action_space.sample()  # 使用 sample 表示随机行动
env.step(action)  # 采取随机行动

上面的代码中,action_space.sample() 是环境默认方法代表随机选择动作。实际上,你也可以手动指定 action_space.contains(0\1\2\3) 实现左下右上。由于 Gym 环境文档普遍不全,可能需要通过 查看源码 发现。

通过输出结果可以看到,env.step() 行动发生之后,环境返回 4 个值,这 4 个值依次对应:
observation (object):冰面的状态,即 Agent 的观测结果。
reward (float):奖励,即先前行为获得的所有回报之和。
done (boolean):判断是否要重新设定(reset)环境,例如此时掉进冰窟窿或拿到飞盘表示游戏终止,即重新设定环境。
info (dict): 调试诊断信息。

observation = env.reset()  # 重置环境

for t in range(20):
    env.render()  # 渲染环境
    action = env.action_space.sample()  # 设定随机行动
    observation, reward, done, info = env.step(action)  # 采取随机行动
    print(observation, reward, done)  # 输出观测结果,奖励以及游戏是否终止的状态
    if done:  # 如果游戏中止
        print("Episode finished after {} timesteps".format(t+1))  # 输出连续行动的时间步长
        break

其实,我们还可以使用 IPython.display 模块让过程在 Notebook 中动态化:

from IPython import display
import time

observation = env.reset()  # 重置环境
for t in range(20):
    env.render()  # 渲染环境
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)  # 采取随机行动
    print(observation, reward, done)
    display.clear_output(wait=True)  # 清除单元格输出
    time.sleep(1)  # 延时 1s 执行
    print("step:", t)
    if done:
        print("Episode finished after {} timesteps".format(t+1))
        break

上面的例子中,你可能会发现每一个 step 都会显示执行的方向(Up,Down,Left,Right),但是智能体并不是每次都向相应方向移动。这是因为环境默认设置了冰面很滑,所以有 1/3 的概率溜走。
不过,我们可以通过重新注册环境参数来取消掉随机性,变成确定性问题。

from gym.envs.registration import register

# 重新注册环境
register(
    id='FrozenLakeNotSlippery-v0',  # 新环境 id
    entry_point='gym.envs.toy_text:FrozenLakeEnv',  # 继承环境
    kwargs={'map_name': '4x4', 'is_slippery': False},  # 参数
    max_episode_steps=100,  # 最大迭代次数
)

上方,我们继承了 FrozenLakeEnv 环境,并重新注册了新环境 FrozenLakeNotSlippery-v0。其中设置 'is_slippery': False 使得环境变成确定性问题。

from IPython import display
import time

env = gym.make('FrozenLakeNotSlippery-v0')  # 加载新环境
observation = env.reset()  # 重置环境
for t in range(20):
    env.render()  # 渲染环境
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)  # 采取随机行动
    print(observation, reward, done)
    display.clear_output(wait=True)  # 清除单元格输出
    time.sleep(1)  # 延时 1s 执行
    print("step:", t)
    if done:
        print("Episode finished after {} timesteps".format(t+1))
        break

这一次,你应该能看到智能体是沿着状态显示的方向准确移动了。

Gym 玩 Atari 打砖块游戏

一般情况下,OpenAI Gym 需要运行在有显卡的环境中,因为大部分环境需要有窗口显示。所以,线上 Jupyter Notebook 使用 Gym 的限制就非常多了。
上一个实验中,我们使用 FrozenLake-v0 文字游戏进行了示例。本次挑战中,你需要参考前面介绍过的 Gym 环境常用 API 来练习另一个打砖块小游戏环境的调用和渲染。这块游戏也是 Atari 雅达利 非常经典的游戏之一。
挑战:加载打砖块小游戏环境 Breakout-v0。

import gym

env = gym.make("Breakout-v0")
env

接下来,我们初步查看环境的样子,你需要渲染环境界面。由于该环境与文字游戏不同,我们需要对其进行简单处理以在 Jupyter Notebook 中显示。
挑战:渲染并可视化环境 Breakout-v0。
规定:需要向 render 方法中添加参数 mode='rgb_array',其可以使环境变成 RGB 数组。最后使用 Matplotlib 提供的 imshow 方法显示图像。

from matplotlib import pyplot as plt
%matplotlib inline

env.reset()  # 运行前一般需要先重置环境
rgb_array = env.render(mode='rgb_array')  # 渲染为数组
plt.imshow(rgb_array)  # 绘图

接下来,我们查看 Breakout-v0 环境提供的动作空间。

env.action_space

Discrete(4) 表示底部滑块(智能体)有 4 个动作,实际上就是向左,向右,快速向左和快速向右。
下面,我们随机选择动作,并迭代 100 次,查看环境的变化。
挑战:随机选择智能体动作迭代 100 次,并打印出每次执行的动作、奖励以及是否重置环境的状态。

from IPython import display

env.reset()
for t in range(100):  # 最长时间步长为 100
    display.display(plt.gcf())
    
    plt.imshow(env.render(mode='rgb_array'))
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)  # 采取随机行动
    print(action, reward, done)
   
    display.clear_output(wait=True)  # 清空每次迭代的静态输出使之可以动态显示
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容