在机器学习领域,特别是强化学习这一分支,OpenAI Gym提供了一个用于开发和比较不同算法的工具包。它支持多种环境,包括经典的游戏、棋盘游戏、二维和三维物理模拟等,使得可以训练智能体、比较它们或开发新的机器学习算法(强化学习)。
OpenAI是一个人工智能研究公司,部分资金来自埃隆·马斯克。其明确的目标是推动和发展对人类有益的友好AI(而不是消灭人类)。
本文将使用OpenAI gym,这是一个开发和比较强化学习算法的优秀工具包。它为学习智能体提供了许多交互环境。
在安装工具包之前,如果使用virtualenv
创建了隔离环境,首先需要激活它:
$ cd $ML_PATH # 机器学习工作目录(例如,$HOME/ml)
$ source my_env/bin/activate # 在Linux或MacOS上
$ .my_envScriptsactivate # 在Windows上
接下来,安装OpenAI Gym(如果不使用虚拟环境,需要添加--user
选项,或者拥有管理员权限):
$ python3 -m pip install -U gym
根据系统,可能还需要安装Mesa OpenGL Utility(GLU)库(例如,在Ubuntu 18.04上需要运行apt install libglu1-mesa
)。这个库将被需要来渲染第一个环境。
打开Python shell或Jupyter notebook或Google Colab,将首先导入所有必要的库,然后使用make()
创建一个环境:
# Python ≥3.5是必需的
import sys
assert sys.version_info >= (3, 5)
# Scikit-Learn ≥0.20是必需的
import sklearn
assert sklearn.__version__ >= "0.20"
确保TensorFlow ≥2.0是必需的:
import tensorflow as tf
from tensorflow import keras
assert tf.__version__ >= "2.0"
如果没有检测到GPU,卷积神经网络(CNNs)在没有GPU的情况下可能会非常慢。如果是在Colab上,可以更改运行时并选择GPU硬件加速器。
让列出所有可用的环境:
gym.envs.registry.all()
Cart-Pole是一个非常简单的环境,由一个可以左右移动的小车和一个垂直放置在其上的杆组成。智能体必须移动小车来保持杆的直立。
env = gym.make('CartPole-v1')
通过调用reset()
方法初始化环境,这将返回一个观察结果:
env.seed(42)
obs = env.reset()
观察结果因环境而异。在这种情况下,它是一个由4个浮点数组成的1D NumPy数组:它们代表小车的横向位置、速度、杆的角度(0 = 垂直)和角速度。
obs
环境可以通过调用其render()
方法进行可视化,可以选择渲染模式(渲染选项取决于环境)。
env.render()
在这个例子中,将设置mode="rgb_array"
以获取环境的图像作为一个NumPy数组:
img = env.render(mode="rgb_array")
img.shape
(400, 600, 3)
智能体需要从“动作空间”(可能的动作集合)中选择一个动作。让看看这个环境的动作空间是什么样的:
env.action_space
Discrete(2)意味着可能的动作是整数0和1,分别代表向左加速(0)或向右加速(1)。其他环境可能有更多的离散动作,或其他类型的动作(例如,连续的)。由于杆向右倾斜(obs[2] > 0),让向右加速小车:
action = 1 # 向右加速
obs, reward, done, info = env.step(action)
注意到小车现在正在向右移动(obs[1] > 0)。杆仍然向右倾斜(obs[2] > 0),但它的角速度现在是负的(obs[3] < 0),所以它可能会在下一步向左倾斜。
让硬编码一个简单的策略,当杆向左倾斜时向左加速,当杆向右倾斜时向右加速。将运行这个策略,看看它在500个episode中获得的平均奖励:
env.seed(42)
def basic_policy(obs):
angle = obs[2]
return 0 if angle < 0 else 1
这个策略非常简单:当杆向左倾斜时,智能体将向左加速;当杆向右倾斜时,智能体将向右加速。将运行这个策略,并观察它在500个episode中获得的平均奖励。
totals = []
for episode in range(500):
episode_rewards = 0
obs = env.reset()
for step in range(200):
action = basic_policy(obs)
obs, reward, done, info = env.step(action)
episode_rewards += reward
if done:
break
totals.append(episode_rewards)
代码应该是自解释的。让看看结果:
np.mean(totals), np.std(totals), np.min(totals), np.max(totals)
(41.718, 8.858356280936096, 24.0, 68.0)
def update_scene(num, frames, patch):
patch.set_data(frames[num])
return patch,
def plot_animation(frames, repeat=False, interval=40):
fig = plt.figure()
patch = plt.imshow(frames[0])
plt.axis('off')
anim = animation.FuncAnimation(
fig, update_scene, fargs=(frames, patch),
frames=len(frames), repeat=repeat, interval=interval)
plt.close()
return anim
plot_animation(frames)