本文介绍了OpenAI Gym多线程环境的实现方法。由于OpenAI Baselines提供的SubprocVecEnv类在使用时会有一些bug,本文用自己的方式对多线程环境进行简单实现。以Breakout为例,效果如图。【注:本文的实现方法未使用多线程(进程)方法,故cpu利用率较低,之后有时间会考虑使用多线程实现】
图 1 多线程breakout环境训练过程
目录
环境初始化
本文采用环境list的方式实现多环境,代码如下:
import gym
import numpy as np
NUM_PROCESSES = 16
envs = [gym.make('Breakout-v0') for i in range(NUM_PROCESSES)]
obs = [env.reset() for env in envs]
obs = np.array(obs)
就是调用了16次gym.make(),然后将得到的env放到一个list中。
obs得到每个环境初始状态构成的list。由于reset()返回的时np.array格式,故将obs转换成array格式。
环境step的处理
用action_np表示你的智能算法返回的array格式的动作,调用step()的代码如下:
# 处理step返回的数据,注意正常调用step时是这样的: obs, reward, done, info = envs[p].step(a)
# 故 results = [(obs, reward, done, info), (obs, reward, done, info), ...]
results = [envs[p].step(a) for p, a in enumerate(action_np)]
# 将step返回的每类值进行整合,如 obs = array([obs1, obs2, ...])
obs = np.array([result[0] for result in results])
reward = np.array([result[1] for result in results])
done = np.array([result[2] for result in results])
info = np.array([result[3] for result in results])
得到的obs,reward,done,info就是每个环境的结果整合之后的array。
此外,注意要对已经done的环境进行reset(),代码如下:
# 将done的环境reset
obs = np.array([envs[p].reset() if d else obs[p] for p, d in enumerate(done)])
# 可用masks表示每个环境是否done
masks = torch.FloatTensor([[0.0] if done_ else [1.0] for done_ in done])
训练时环境的实时显示
这部分参考OpenAI Baselines提供的SubprocVecEnv类的实现方式。定义显示环境的类Environment和函数display_multi_process,代码如下:
import gym
import numpy as np
from gym.envs.classic_control import rendering
class Environment():
def __init__(self):
self.viewer = rendering.SimpleImageViewer()
def display_multi_process(self, envs):
# 将所有环境中的画面进行处理,形成一个大的图像,由于显示
img_nhwc = np.array([env.render('rgb_array') for env in envs])
N, h, w, c = img_nhwc.shape # (NUM_PROCESSES, 210, 160, 3)
H = int(np.ceil(np.sqrt(N))) # 大图像中每列小图像个数
W = int(np.ceil(float(N)/H)) # 大图像中每行小图像个数
img_HWhwc = img_nhwc.reshape(H, W, h, w, c) # 将N拆分成H*W
img_HhWwc = img_HWhwc.transpose(0, 2, 1, 3, 4) # 调换顺序
img_Hh_Ww_c = img_HhWwc.reshape(H*h, W*w, c) # 组合成大图像
self.viewer.imshow(img_Hh_Ww_c) # 显示图像
在训练时调用self.display_multi_process(envs)即可得到如图 1 所示的训练界面。