简体   繁体   English

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

[英]How to run OpenAI Gym .render() over a server

I am running a python 2.7 script on a p2.xlarge AWS server through Jupyter (Ubuntu 14.04).我正在通过 Jupyter(Ubuntu 14.04)在 p2.xlarge AWS服务器上运行 python 2.7 脚本。 I would like to be able to render my simulations.我希望能够渲染我的模拟。

Minimal working example最小工作示例

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

env.render() makes (among other things) the following errors: 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"

I would like to some how be able to see the simulations.我想知道一些如何能够看到模拟。 It would be ideal if I could get it inline, but any display method would be nice.如果我可以将它内联,那将是理想的,但任何显示方法都很好。

Edit : This is only an issue with some environments, like classic control.编辑:这只是某些环境的问题,例如经典控件。


Update I更新我

Inspired by this I tried the following, instead of the xvfb-run -s \\"-screen 0 1400x900x24\\" python <your_script.py> (which I couldn't get to work).灵感来自这个我尝试以下,而不是xvfb-run -s \\"-screen 0 1400x900x24\\" python <your_script.py>我不能去工作)。

xvfb-run -a jupyter notebook

Running the original script I now get instead运行我现在得到的原始脚本

GLXInfoException: pyglet requires an X server with GLX

Update II更新二

Issue #154 seems relevant.问题#154似乎相关。 I tried disabling the pop-up, and directly creating the RGB colors我尝试禁用弹出窗口,并直接创建 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)) 

I get ImportError: cannot import name gl_info .我收到ImportError: cannot import name gl_info


Update III更新三

With inspiration from @ Torxed I tried creating a video file, and then rendering it (a fully satisfying solution).受@ Torxed 的启发,我尝试创建一个视频文件,然后渲染它(一个完全令人满意的解决方案)。

Using the code from ' Recording and uploading results '使用“记录和上传结果”中的代码

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()

I tried following your suggestions, but got ImportError: cannot import name gl_info from when running env.monitor.start(... .我尝试遵循您的建议,但得到了ImportError: cannot import name gl_info from when running env.monitor.start(... .

From my understanding the problem is that OpenAI uses pyglet , and pyglet 'needs' a screen in order to compute the RGB colors of the image that is to be rendered.根据我的理解,问题在于 OpenAI 使用pyglet ,而pyglet “需要”一个屏幕来计算要渲染的图像的 RGB 颜色。 It is therefore necessary to trick python to think that there is a monitor connected因此有必要欺骗python认为有一个监视器连接


Update IV更新四

FYI there are solutions online using bumblebee that seem to work.仅供参考,有一些使用大黄蜂的在线解决方案似乎有效。 This should work if you have control over the server, but since AWS run in a VM I don't think you can use this.如果您可以控制服务器,这应该可以工作,但是由于 AWS 在 VM 中运行,我认为您不能使用它。


Update V更新五

Just if you have this problem, and don't know what to do (like me) the state of most environments are simple enough that you can create your own rendering mechanism.只是如果你有这个问题,并且不知道该怎么做(像我一样)大多数环境的状态很简单,你可以创建自己的渲染机制。 Not very satisfying, but.. you know.不是很满意,但是……你知道。

Got a simple solution working:有一个简单的解决方案工作:

车杆

If on a linux server, open jupyter with 如果在 linux 服务器上,请使用以下命令打开 jupyter
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())
In Jupyter 在 Jupyter 中
import matplotlib.pyplot as plt %matplotlib inline from IPython import display
After each step 每一步之后
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())

Note: if your environment is not unwrapped , pass env.env to show_state .注意:如果你的环境是不unwrapped ,通过env.envshow_state

This GitHub issue gave an answer that worked great for me.这个GitHub 问题给出了一个对我很有用的答案。 It's nice because it doesn't require any additional dependencies (I assume you already have matplotlib ) or configuration of the server.这很好,因为它不需要任何额外的依赖项(我假设你已经有了matplotlib )或服务器的配置。

Just run, eg:只需运行,例如:

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()

Using mode='rgb_array' gives you back a numpy.ndarray with the RGB values for each position, and matplotlib 's imshow (or other methods) displays these nicely.使用mode='rgb_array'会返回一个numpy.ndarray ,其中包含每个位置的 RGB 值,并且matplotlibimshow (或其他方法)可以很好地显示这些值。

Note that if you're rendering multiple times in the same cell, this solution will plot a separate image each time.需要注意的是,如果你在同一个单元格呈现多次,该解决方案将每次绘制一个单独的图像。 This is probably not what you want.这可能不是您想要的。 I'll try to update this if I figure out a good workaround for that.如果我找到一个好的解决方法,我会尝试更新它。

Update to render multiple times in one cell更新以在一个单元格中多次渲染

Based on this StackOverflow answer, here's a working snippet (note that there may be more efficient ways to do this with an interactive plot; this way seems a little laggy on my machine):基于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)

Update to increase efficiency更新以提高效率

On my machine, this was about 3x faster.在我的机器上,这大约快了 3 倍。 The difference is that instead of calling imshow each time we render, we just change the RGB data on the original plot.不同之处在于,不是每次渲染时都调用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)

I managed to run and render openai/gym (even with mujoco) remotely on a headless server.我设法在无头服务器上远程运行和渲染 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

Usage:用法:

DISPLAY=:0 ipython2

Example:示例:

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)

I think we should just capture renders as video by using OpenAI Gym wrappers.Monitor and then display it within the Notebook.我认为我们应该使用 OpenAI Gym wrappers.Monitor将渲染捕获为视频,然后将其显示在 Notebook 中。

Example:示例:

Dependencies依赖关系

!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()

Capture as video捕获为视频

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()

Display within Notebook在笔记本内显示

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")

I hope it helps.我希望它有帮助。 ;) ;)

There's also this solution using pyvirtualdisplay (an Xvfb wrapper).还有这个使用pyvirtualdisplay (Xvfb 包装器)的解决方案 One thing I like about this solution is you can launch it from inside your script, instead of having to wrap it at launch:我喜欢这个解决方案的一件事是您可以从脚本内部启动它,而不必在启动时包装它:

from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()

I ran into this myself.我自己遇到了这个。 Using xvfb as X-server somehow clashes with the Nvidia drivers.使用 xvfb 作为 X 服务器在某种程度上与 Nvidia 驱动程序发生冲突。 But finallythis post pointed me into the right direction.但最后这篇文章为我指明了正确的方向。 Xvfb works without any problems if you install the Nvidia driver with the -no-opengl-files option and CUDA with --no-opengl-libs option.如果您使用-no-opengl-files选项安装 Nvidia 驱动程序并使用--no-opengl-libs选项安装 CUDA,则 Xvfb 可以正常工作。 If you know this, it should work.如果你知道这一点,它应该工作。 But as it took me quite some time till I figured this out and it seems like I'm not the only one running into problems with xvfb and the nvidia drivers.但是因为我花了很长时间才弄明白这一点,而且似乎我不是唯一遇到 xvfb 和 nvidia 驱动程序问题的人。

I wrote down all necessary steps to set everything up on an AWS EC2 instance with Ubuntu 16.04 LTS here.我在这里写下了在带有 Ubuntu 16.04 LTS 的 AWS EC2 实例上设置所有内容的所有必要步骤

I avoided the issues with using matplotlib by simply using PIL, Python Image Library:我通过简单地使用 PIL、Python 图像库避免了使用 matplotlib 的问题:

import gym, PIL
env = gym.make('SpaceInvaders-v0')
array = env.reset()
PIL.Image.fromarray(env.render(mode='rgb_array'))

I found that I didn't need to set the XV frame buffer.我发现我不需要设置 XV 帧缓冲区。

I was looking for a solution that works in Colaboratory and ended up with this我一直在寻找一个适用于 Colaboratory 的解决方案,最终得到了这个

from IPython import display
import numpy as np
import time

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

import PIL.Image
import io


def showarray(a, fmt='png'):
    a = np.uint8(a)
    f = io.BytesIO()
    ima = PIL.Image.fromarray(a).save(f, fmt)
    return f.getvalue()

imagehandle = display.display(display.Image(data=showarray(env.render(mode='rgb_array')), width=450), display_id='gymscr')

while True:
    time.sleep(0.01)
    env.step(env.action_space.sample()) # take a random action
    display.update_display(display.Image(data=showarray(env.render(mode='rgb_array')), width=450), display_id='gymscr')

EDIT 1:编辑 1:

You could use xvfbwrapper for the Cartpole environment.您可以将 xvfbwrapper 用于 Cartpole 环境。

from IPython import display
from xvfbwrapper import Xvfb
import numpy as np
import time
import pyglet
import gym
import PIL.Image
import io    

vdisplay = Xvfb(width=1280, height=740)
vdisplay.start()

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

def showarray(a, fmt='png'):
    a = np.uint8(a)
    f = io.BytesIO()
    ima = PIL.Image.fromarray(a).save(f, fmt)
    return f.getvalue()

imagehandle = display.display(display.Image(data=showarray(env.render(mode='rgb_array')), width=450), display_id='gymscr')


for _ in range(1000):
  time.sleep(0.01)
  observation, reward, done, info = env.step(env.action_space.sample()) # take a random action
  display.update_display(display.Image(data=showarray(env.render(mode='rgb_array')), width=450), display_id='gymscr')


vdisplay.stop()

If you're working with standard Jupyter, there's a better solution though.如果您使用标准 Jupyter,则有更好的解决方案。 You can use the CommManager to send messages with updated Data URLs to your HTML output.您可以使用 CommManager 将带有更新数据 URL 的消息发送到您的 HTML 输出。

IPython Inline Screen Example IPython 内联屏幕示例

In Colab the CommManager is not available.在 Colab 中,CommManager 不可用。 The more restrictive output module has a method called eval_js() which seems to be kind of slow.更具限制性的输出模块有一个名为 eval_js() 的方法,它似乎有点慢。

Referencing my other answer here: Display OpenAI gym in Jupyter notebook only在此处引用我的其他答案: 仅在 Jupyter 笔记本中显示 OpenAI 健身房

I made a quick working example here which you could fork: https://kyso.io/eoin/openai-gym-jupyter with two examples of rendering in Jupyter - one as an mp4, and another as a realtime gif.我在这里做了一个快速的工作示例,你可以分叉: https ://kyso.io/eoin/openai-gym-jupyter 有两个在 Jupyter 中渲染的示例 - 一个作为 mp4,另一个作为实时 gif。

The .mp4 example is quite simple. .mp4 示例非常简单。

import gym
from gym import wrappers

env = gym.make('SpaceInvaders-v0')
env = wrappers.Monitor(env, "./gym-results", force=True)
env.reset()
for _ in range(1000):
    action = env.action_space.sample()
    observation, reward, done, info = env.step(action)
    if done: break
env.close()

Then in a new cell Jupyter cell, or download it from the server onto some place where you can view the video.然后在一个新的单元格 Jupyter 单元格中,或将它从服务器下载到某个可以观看视频的地方。

import io
import base64
from IPython.display import HTML

video = io.open('./gym-results/openaigym.video.%s.video000000.mp4' % env.file_infix, 'r+b').read()
encoded = base64.b64encode(video)
HTML(data='''
    <video width="360" height="auto" alt="test" controls><source src="data:video/mp4;base64,{0}" type="video/mp4" /></video>'''
.format(encoded.decode('ascii')))

If your on a server with public access you could run python -m http.server in the gym-results folder and just watch the videos there.如果您在具有公共访问权限的服务器上,您可以在健身房结果文件夹中运行python -m http.server并在那里观看视频。

I encountered the same problem and stumbled upon the answers here.我遇到了同样的问题并偶然发现了这里的答案。 Mixing them helped me to solve the problem.混合它们帮助我解决了这个问题。

Here's a step by step solution:这是一个分步解决方案:

Install the following:安装以下内容:

apt-get install -y python-opengl xvfb

Start your jupyter notebook via the following command:通过以下命令启动您的 jupyter 笔记本:

xvfb-run -s "-screen 0 1400x900x24" jupyter notebook

Inside the notebook:笔记本内部:

import gym
import matplotlib.pyplot as plt
%matplotlib inline

env = gym.make('MountainCar-v0') # insert your favorite environment
env.reset()
plt.imshow(env.render(mode='rgb_array')

Now you can put the same thing in a loop to render it multiple times.现在您可以将相同的内容放入循环中以多次渲染它。

from IPython import display

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)

Hope this works for anyone else still facing an issue.希望这适用于仍然面临问题的其他人。 Thanks to Andrews and Nathan for their answers.感谢安德鲁斯内森的回答。

I had the same problem and I_like_foxes solution to reinstall nvidia drivers with no opengl fixed things.我有同样的问题和 I_like_foxes 解决方案来重新安装 nvidia 驱动程序,而没有 opengl 固定的东西。 Here are the commands I used for Ubuntu 16.04 and GTX 1080ti https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78这是我用于 Ubuntu 16.04 和 GTX 1080ti https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78的命令

This might be a complete workaround, but I used a docker image with a desktop environment, and it works great.这可能是一个完整的解决方法,但我在桌面环境中使用了 docker 映像,并且效果很好。 The docker image is at https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc/ docker 镜像位于https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc/

The command to run is要运行的命令是

docker run -p 6080:80 dorowu/ubuntu-desktop-lxde-vnc

Then browse http://127.0.0.1:6080/ to access the Ubuntu desktop.然后浏览http://127.0.0.1:6080/访问 Ubuntu 桌面。

Below are a gif showing it the Mario bros gym environment running and being rendered.下面是一个 gif,显示了正在运行和渲染的马里奥兄弟健身房环境。 As you can see, it is fairly responsive and smooth.如您所见,它相当灵敏且流畅。

在此处输入图片说明

I created this mini-package which allows you to render your environment onto a browser by just adding one line to your code.我创建了这个迷你包,它允许您通过在代码中添加一行来将您的环境渲染到浏览器上。

Put your code in a function and replace your normal env.render() with yield env.render(mode='rgb_array') .将您的代码放在一个函数中,并将您的普通env.render()替换为yield env.render(mode='rgb_array') Encapsulate this function with the render_browser decorator.render_browser装饰器封装这个函数。

import gym
from render_browser import render_browser

@render_browser
def test_policy(policy):
    # Your function/code here.
    env = gym.make('Breakout-v0')
    obs = env.reset()

    while True:
        yield env.render(mode='rgb_array')
        # ... run policy ...
        obs, rew, _, _ = env.step(action)

test_policy(policy)    

When you visit your_ip:5000 on your browser, test_policy() will be called and you'll be able to see the rendered environment on your browser window.当您在浏览器上访问your_ip:5000时,将调用test_policy()并且您将能够在浏览器窗口中看到渲染的环境。

在此处输入图片说明

In my IPython environment, Andrew Schreiber's solution can't plot image smoothly.在我的 IPython 环境中,Andrew Schreiber 的解决方案无法顺利绘制图像。 The following is my solution:以下是我的解决方案:

If on a linux server, open jupyter with如果在 linux 服务器上,请使用以下命令打开 jupyter

$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook

In Jupyter在 Jupyter 中

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

Display iteration:显示迭代:

done = False
obs = env.reset()

fig = plt.figure()
ax = fig.add_subplot(111)
plt.ion()

fig.show()
fig.canvas.draw()

while not done:
    # action = pi.act(True, obs)[0] # pi means a policy which produces an action, if you have
    # obs, reward, done, info = env.step(action) # do action, if you have
    env_rnd = env.render(mode='rgb_array')
    ax.clear()
    ax.imshow(env_rnd)
    fig.canvas.draw()
    time.sleep(0.01)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM