如何在服务器上运行OpenAI Gym .render()

Tok*_*rby 54 python pyglet xvfb jupyter-notebook openai-gym

我正在通过Jupyter(Ubuntu 14.04)在p2.xlarge AWS服务器上运行python 2.7脚本.我希望能够渲染我的模拟.

最小的工作示例

import gym
env = gym.make('CartPole-v0')
env.reset()
env.render()
Run Code Online (Sandbox Code Playgroud)

env.render() 使(除其他外)以下错误:

...
HINT: make sure you have OpenGL install. On Ubuntu, you can run 
'apt-get install python-opengl'. If you're running on a server, 
you may need a virtual frame buffer; something like this should work: 
'xvfb-run -s \"-screen 0 1400x900x24\" python <your_script.py>'")
...
NoSuchDisplayException: Cannot connect to "None"
Run Code Online (Sandbox Code Playgroud)

我想有些人能够看到模拟.如果我可以将它内联,那将是理想的,但任何显示方法都会很好.

编辑:这只是某些环境的问题,如经典控件.


更新我

灵感来自这个我尝试以下,而不是xvfb-run -s \"-screen 0 1400x900x24\" python <your_script.py>(我不能去上班).

xvfb-run -a jupyter notebook
Run Code Online (Sandbox Code Playgroud)

运行原始脚本我现在得到了

GLXInfoException: pyglet requires an X server with GLX
Run Code Online (Sandbox Code Playgroud)

更新II

问题#154似乎相关.我尝试禁用弹出窗口,并直接创建RGB颜色

import gym
env = gym.make('CartPole-v0')
env.reset()

img = env.render(mode='rgb_array', close=True)  
print(type(img)) # <--- <type 'NoneType'>

img = env.render(mode='rgb_array', close=False) # <--- ERROR
print(type(img)) 
Run Code Online (Sandbox Code Playgroud)

我得到ImportError: cannot import name gl_info.


更新III

借助@ Torxed的灵感,我尝试创建一个视频文件,然后渲染它(一个完全令人满意的解决方案).

使用" 录制和上传结果 "中的代码

import gym

env = gym.make('CartPole-v0')
env.monitor.start('/tmp/cartpole-experiment-1', force=True)
observation = env.reset()
for t in range(100):
#    env.render()
    print(observation)
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)
    if done:
        print("Episode finished after {} timesteps".format(t+1))
        break

env.monitor.close()
Run Code Online (Sandbox Code Playgroud)

我试着按照你的建议,但从ImportError: cannot import name gl_info跑步时得到了env.monitor.start(....

根据我的理解,问题在于OpenAI使用pygletpyglet"需要"一个屏幕来计算要渲染的图像的RGB颜色.因此有必要欺骗python认为连接了一个监视器


更新IV

仅供参考,网上有使用大黄蜂的解决方案似乎有效.如果您可以控制服务器,这应该有效,但由于AWS在VM中运行,我认为您不能使用它.


更新V.

如果您遇到此问题,并且不知道该怎么做(像我一样),大多数环境的状态都很简单,您可以创建自己的渲染机制.不是很满意,但是......你知道.

And*_*ber 25

得到一个简单的解决方案:

CartPole

如果在linux服务器上,打开jupyter
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
Run Code Online (Sandbox Code Playgroud) 在Jupyter
import matplotlib.pyplot as plt
%matplotlib inline
from IPython import display
Run Code Online (Sandbox Code Playgroud) 每一步之后
def show_state(env, step=0, info=""):
    plt.figure(3)
    plt.clf()
    plt.imshow(env.render(mode='rgb_array'))
    plt.title("%s | Step: %d %s" % (env._spec.id,step, info))
    plt.axis('off')

    display.clear_output(wait=True)
    display.display(plt.gcf())
Run Code Online (Sandbox Code Playgroud)

注意:如果您的环境不是unwrapped,请env.env转到show_state.

  • 效果很好,谢谢,但是环境仍然在外部窗口中打开(我在本地运行它,而不是在远程服务器中运行)。关于如何防止这种情况有什么想法吗? (2认同)

Nat*_*han 13

这个 GitHub问题给出了一个对我有用的答案.这很好,因为它不需要任何额外的依赖(我假设你已经拥有matplotlib)或服务器的配置.

跑步,例如:

import gym
import matplotlib.pyplot as plt
%matplotlib inline

env = gym.make('Breakout-v0') # insert your favorite environment
render = lambda : plt.imshow(env.render(mode='rgb_array'))
env.reset()
render()
Run Code Online (Sandbox Code Playgroud)

使用mode='rgb_array'给你回一个numpy.ndarray与每个位置上的RGB值,和matplotlibimshow(或其它方法)显示这些很好.

请注意,如果您需要将多个在同一细胞时,这种解决方案将每次绘制一个单独的图像.这可能不是你想要的.如果我找到一个好的解决方法,我会尝试更新它.

更新以在一个单元格中多次渲染

基于这个 StackOverflow答案,这是一个工作片段(请注意,使用交互式绘图可能有更有效的方法来执行此操作;这种方式在我的机器上看起来有点滞后):

import gym
from IPython import display
import matplotlib.pyplot as plt
%matplotlib inline

env = gym.make('Breakout-v0')
env.reset()
for _ in range(100):
    plt.imshow(env.render(mode='rgb_array'))
    display.display(plt.gcf())
    display.clear_output(wait=True)
    action = env.action_space.sample()
    env.step(action)
Run Code Online (Sandbox Code Playgroud)

更新以提高效率

在我的机器上,这大约快了3倍.不同之处在于imshow,我们只是在原始图上更改RGB数据,而不是每次渲染时调用.

import gym
from IPython import display
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline

env = gym.make('Breakout-v0')
env.reset()
img = plt.imshow(env.render(mode='rgb_array')) # only call this once
for _ in range(100):
    img.set_data(env.render(mode='rgb_array')) # just update the data
    display.display(plt.gcf())
    display.clear_output(wait=True)
    action = env.action_space.sample()
    env.step(action)
Run Code Online (Sandbox Code Playgroud)

  • @Nathan你的解决方案还有一个问题.有些环节似乎有办法绕过窗口创建而其他环境没有.例如,如果你想尝试这个,在你的例子中用`env = gym.make('CartPole-v0')`替换`env = gym.make('Breakout-v0')`你会看到什么我的意思是.'Breakout'碰巧是一个atari游戏,它使用`atari_py.ALEInterface()`作为渲染器并返回一个图像.请参阅https://github.com/openai/gym/blob/master/gym/envs/atari/atari_env.py#L113 (3认同)

Van*_*Van 10

我设法在无头服务器上远程运行并渲染openai/gym(即使是mujoco).

# Install and configure X window with virtual screen
sudo apt-get install xserver-xorg libglu1-mesa-dev freeglut3-dev mesa-common-dev libxmu-dev libxi-dev
# Configure the nvidia-x
sudo nvidia-xconfig -a --use-display-device=None --virtual=1280x1024
# Run the virtual screen in the background (:0)
sudo /usr/bin/X :0 &
# We only need to setup the virtual screen once

# Run the program with vitural screen
DISPLAY=:0 <program>

# If you dont want to type `DISPLAY=:0` everytime
export DISPLAY=:0
Run Code Online (Sandbox Code Playgroud)

用法:

DISPLAY=:0 ipython2
Run Code Online (Sandbox Code Playgroud)

例:

import gym
env = gym.make('Ant-v1')
arr = env.render(mode='rgb_array')
print(arr.shape)
# plot or save wherever you want
# plt.imshow(arr) or scipy.misc.imsave('sample.png', arr)
Run Code Online (Sandbox Code Playgroud)


Trầ*_*Sơn 9

我认为我们应该使用OpenAI Gym将渲染作为视频捕获wrappers.Monitor ,然后在Notebook中显示.

例:

依赖

!apt install python-opengl
!apt install ffmpeg
!apt install xvfb
!pip3 install pyvirtualdisplay

# Virtual display
from pyvirtualdisplay import Display

virtual_display = Display(visible=0, size=(1400, 900))
virtual_display.start()
Run Code Online (Sandbox Code Playgroud)

捕获为视频

import gym
from gym import wrappers

env = gym.make("SpaceInvaders-v0")
env = wrappers.Monitor(env, "/tmp/SpaceInvaders-v0")

for episode in range(2):
    observation = env.reset()
    step = 0
    total_reward = 0

    while True:
        step += 1
        env.render()
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        total_reward += reward
        if done:
            print("Episode: {0},\tSteps: {1},\tscore: {2}"
                  .format(episode, step, total_reward)
            )
            break
env.close()
Run Code Online (Sandbox Code Playgroud)

在笔记本中显示

import os
import io
import base64
from IPython.display import display, HTML

def ipython_show_video(path):
    """Show a video at `path` within IPython Notebook
    """
    if not os.path.isfile(path):
        raise NameError("Cannot access: {}".format(path))

    video = io.open(path, 'r+b').read()
    encoded = base64.b64encode(video)

    display(HTML(
        data="""
        <video alt="test" controls>
        <source src="data:video/mp4;base64,{0}" type="video/mp4" />
        </video>
        """.format(encoded.decode('ascii'))
    ))

ipython_show_video("/tmp/SpaceInvaders-v0/openaigym.video.4.10822.video000000.mp4")
Run Code Online (Sandbox Code Playgroud)

我希望它有所帮助.;)


mda*_*ust 8

还有这个解决方案使用pyvirtualdisplay(一个Xvfb包装器).我喜欢这个解决方案的一件事是你可以从脚本中启动它,而不必在启动时包装它:

from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
Run Code Online (Sandbox Code Playgroud)


I_l*_*xes 7

我自己也碰到了这个.使用xvfb作为X服务器以某种方式与Nvidia驱动程序冲突.但最后这篇文章指出了我正确的方向.如果使用-no-opengl-files选项和带有--no-opengl-libs选项的CUDA 安装Nvidia驱动程序,Xvfb可以正常工作.如果你知道这一点,它应该工作.但是因为我花了很长时间才弄明白这一点,看起来我不是唯一一个遇到xvfb和nvidia驱动程序问题的人.

我写下了所有必要的步骤,在这里使用Ubuntu 16.04 LTS AWS EC2实例上设置所有内容.