OpenAI 的介绍

强化学习的一个挑战是,为了训练智能体,首先需要有一个工作环境。如果你想设计一个可以学习 Atari 游戏的程序,你需要一个 Atari 游戏模拟器。如果你想设计一个步行机器人,那么环境就是真实的世界,你可以直接在这个环境中训练你的机器人,但是这有其局限性:如果机器人从悬崖上掉下来,你不能仅仅点击“撤消”。你也不能加快时间;增加更多的计算能力不会让机器人移动得更快。一般来说,同时训练 1000 个机器人是非常昂贵的。简而言之,训练在现实世界中是困难和缓慢的,所以你通常需要一个模拟环境,至少需要引导训练。

OpenAI gym 是一个工具包,它提供各种各样的模拟环境(Atari 游戏,棋盘游戏,2D 和 3D 物理模拟等等),所以你可以训练,比较,或开发新的 RL 算法。

让我们安装 OpenAI gym。可通过pip安装:

  1. $ pip install --upgrade gym

接下来打开 Python shell 或 Jupyter 笔记本创建您的第一个环境:

  1. >>> import gym
  2. >>> env = gym.make("CartPole-v0")
  3. [2016-10-14 16:03:23,199] Making new env: MsPacman-v0
  4. >>> obs = env.reset()
  5. >>> obs
  6. array([-0.03799846,-0.03288115,0.02337094,0.00720711])
  7. >>> env.render()

使用make()函数创建一个环境,在此例中是 CartPole 环境。这是一个 2D 模拟,其中推车可以被左右加速,以平衡放置在它上面的平衡杆(见图 16-4)。在创建环境之后,我们需要使用reset()初始化。这会返回第一个观察结果。观察取决于环境的类型。对于 CartPole 环境,每个观测是包含四个浮点的 1D Numpy 向量:这些浮点数代表推车的水平位置(0 为中心)、其速度、杆的角度(0 维垂直)及其角速度。最后,render()方法显示如图 16-4 所示的环境。

图16-4

如果你想让render()让图像以一个 NUMPY 数组格式返回,可以将mode参数设置为rgb_array(注意其他环境可能支持不同的模式):

  1. >>> img = env.render(mode="rgb_array")
  2. >>> img.shape # height, width, channels (3=RGB)
  3. (400, 600, 3)

不幸的是,即使将mode参数设置为rgb_array,CartPole(和其他一些环境)还是会将将图像呈现到屏幕上。避免这种情况的唯一方式是使用一个 fake X 服务器,如 XVFB 或 XDimMy。例如,可以使用以下命令安装 XVFB 和启动 Python:xvfb-run -s "screen 0 1400x900x24" python。或者使用xvfbwrapper包。

让我们来询问环境什么动作是可能的:

  1. >>> env.action_space
  2. Discrete(2)

Discrete(2)表示可能的动作是整数 0 和 1,表示向左(0)或右(1)的加速。其他环境可能有更多的动作,或者其他类型的动作(例如,连续的)。因为杆子向右倾斜,让我们向右加速推车:

  1. >>> action = 1 # accelerate right
  2. >>> obs, reward, done, info = env.step(action)
  3. >>> obs
  4. array([-0.03865608, 0.16189797, 0.02351508, -0.27801135])
  5. >>> reward
  6. 1.0
  7. >>> done
  8. False
  9. >>> info
  10. {}

step()表示执行给定的动作并返回四个值:

obs:

这是新的观测,小车现在正在向右走(obs[1]>0,注:当前速度为正,向右为正)。平衡杆仍然向右倾斜(obs[2]>0),但是他的角速度现在为负(obs[3]<0),所以它在下一步后可能会向左倾斜。

reward

在这个环境中,无论你做什么,每一步都会得到 1.0 奖励,所以游戏的目标就是尽可能长的运行。

done

当游戏结束时这个值会为True。当平衡杆倾斜太多时会发生这种情况。之后,必须重新设置环境才能重新使用。

info

该字典可以在其他环境中提供额外的调试信息。这些数据不应该用于训练(这是作弊)。

让我们硬编码一个简单的策略,当杆向左倾斜时加速左边,当杆向右倾斜时加速。我们使用这个策略来获得超过 500 步的平均回报:

  1. def basic_policy(obs):
  2. angle = obs[2]
  3. return 0 if angle < 0 else 1
  4. totals = []
  5. for episode in range(500):
  6. episode_rewards = 0
  7. obs = env.reset()
  8. for step in range(1000): # 最多1000 步,我们不想让它永远运行下去
  9. action = basic_policy(obs)
  10. obs, reward, done, info = env.step(action)
  11. episode_rewards += reward
  12. if done:
  13. break
  14. totals.append(episode_rewards)

这个代码希望能自我解释。让我们看看结果:

  1. >>> import numpy as np
  2. >>> np.mean(totals), np.std(totals), np.min(totals), np.max(totals)
  3. (42.125999999999998, 9.1237121830974033, 24.0, 68.0)

即使有 500 次尝试,这一策略从未使平衡杆在超过 68 个连续的步骤里保持直立。这不太好。如果你看一下 Juyter Notebook 中的模拟,你会发现,推车越来越强烈地左右摆动,直到平衡杆倾斜太多。让我们看看神经网络是否能提出更好的策略。