93

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

最小的工作示例

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

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"

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

编辑:这只是某些环境的问题,例如经典控制。


更新一

受此启发,尝试了以下操作,而不是xvfb-run -s \"-screen 0 1400x900x24\" python <your_script.py>(我无法开始工作)。

xvfb-run -a jupyter notebook

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

GLXInfoException: pyglet requires an X server with GLX

更新二

问题#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)) 

我明白了ImportError: cannot import name gl_info


更新三

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

我尝试遵循您的建议,但从ImportError: cannot import name gl_info运行时得到env.monitor.start(...

据我了解,问题在于 OpenAI 使用pyglet,并且pyglet“需要”一个屏幕来计算要渲染的图像的 RGB 颜色。因此有必要欺骗python认为有一个监视器连接


更新四

仅供参考,使用 bumblebee 的在线解决方案似乎有效。如果您可以控制服务器,这应该可以工作,但是由于 AWS 在 VM 中运行,我认为您不能使用它。


更新 V

如果你有这个问题,并且不知道该怎么做(像我一样),大多数环境的状态都很简单,你可以创建自己的渲染机制。不是很令人满意,但是……你知道的。

4

14 回答 14

39

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

购物车

如果在 linux 服务器上,请使用以下命令打开 jupyter
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
在朱庇特
import matplotlib.pyplot as plt
%matplotlib inline
from IPython import display
每一步之后
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())

注意:如果您的环境不是unwrapped,请传递env.envshow_state.

于 2017-07-19T00:47:42.767 回答
25

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

Usingmode='rgb_array'为您返回 anumpy.ndarray每个位置的 RGB 值,并且matplotlib's imshow(或其他方法)很好地显示这些。

请注意,如果您在同一个单元格中多次渲染此解决方案将每次绘制单独的图像。这可能不是你想要的。如果我找到一个好的解决方法,我会尝试更新它。

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

基于这个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)

更新以提高效率

在我的机器上,这大约快 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)
于 2017-06-08T04:17:42.780 回答
15

我认为我们应该使用 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()

捕获为视频

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

在笔记本中显示

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

我希望它有所帮助。;)

于 2018-07-05T04:39:52.037 回答
14

我设法在无头服务器上远程运行和渲染 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

用法:

DISPLAY=:0 ipython2

例子:

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)
于 2018-01-13T05:34:13.913 回答
12

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

from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
于 2017-12-25T11:06:19.513 回答
9

我自己遇到了这个。使用 xvfb 作为 X-server 会与 Nvidia 驱动程序发生冲突。但最后这篇文章为我指明了正确的方向。-no-opengl-files如果您安装带有选项的 Nvidia 驱动程序和带有选项的 CUDA,Xvfb 可以正常工作--no-opengl-libs。如果你知道这一点,它应该工作。但是我花了很长时间才弄清楚这一点,而且似乎我不是唯一一个遇到 xvfb 和 nvidia 驱动程序问题的人。

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

于 2016-11-13T21:35:19.367 回答
3

在这里引用我的另一个答案:仅在 Jupyter 笔记本中显示 OpenAI 健身房

我在这里做了一个快速工作的例子,你可以分叉:https : //kyso.io/eoin/openai-gym-jupyter 有两个在 Jupyter 中渲染的例子——一个是 mp4,另一个是实时 gif。

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

然后在一个新的单元格 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')))

如果您在具有公共访问权限的服务器上,您可以python -m http.server在gym-results 文件夹中运行并在那里观看视频。

于 2019-01-11T15:08:26.887 回答
3

我遇到了同样的问题,偶然发现了这里的答案。混合它们帮助我解决了这个问题。

这是一步一步的解决方案:

安装以下内容:

apt-get install -y python-opengl xvfb

通过以下命令启动您的 jupyter notebook:

xvfb-run -s "-screen 0 1400x900x24" jupyter 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')

现在您可以将相同的东西放在一个循环中以多次渲染它。

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)

希望这适用于其他仍然面临问题的人。感谢AndrewsNathan的回答。

于 2020-04-17T10:01:14.600 回答
2

我一直在寻找一种适用于 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')

编辑1:

您可以将 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()

如果您使用的是标准 Jupyter,那么有一个更好的解决方案。您可以使用 CommManager 将带有更新数据 URL 的消息发送到您的 HTML 输出。

IPython 内联屏幕示例

在 Colab 中,CommManager 不可用。更严格的输出模块有一个名为 eval_js() 的方法,它似乎有点慢。

于 2018-09-22T17:43:42.433 回答
2

我通过简单地使用 Python Image Library PIL 避免了使用 matplotlib 的问题:

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

我发现我不需要设置 XV 帧缓冲区。

于 2018-01-08T00:27:46.927 回答
1

我有同样的问题和 I_like_foxes 解决方案来重新安装没有 opengl 修复的东西的 nvidia 驱动程序。这是我用于 Ubuntu 16.04 和 GTX 1080ti 的命令 https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78

于 2017-08-03T21:07:50.100 回答
1

这可能是一个完整的解决方法,但我在桌面环境中使用了 docker 映像,效果很好。泊坞窗图像位于https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc/

要运行的命令是

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

然后浏览http://127.0.0.1:6080/访问 Ubuntu 桌面。

下面是一个 gif,显示了正在运行和渲染的 Mario bros 健身房环境。如您所见,它反应灵敏且流畅。

在此处输入图像描述

于 2019-03-19T15:02:18.780 回答
0

我创建了这个迷你包,它允许您通过在代码中添加一行来将您的环境渲染到浏览器上。

将您的代码放在一个函数中,并env.render()yield env.render(mode='rgb_array'). 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)    

当您your_ip:5000在浏览器上访问时,test_policy()将被调用,您将能够在浏览器窗口中看到渲染的环境。

在此处输入图像描述

于 2020-09-10T11:04:16.557 回答
-1

在我的 IPython 环境中,Andrew Schreiber 的解决方案无法顺利绘制图像。以下是我的解决方案:

如果在 linux 服务器上,请使用以下命令打开 jupyter

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

在朱庇特

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

显示迭代:

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)
于 2018-08-26T14:31:18.370 回答