我正在通过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"
我想知道如何能够看到模拟。如果我可以将其内联,那将是理想的,但任何显示方法都会很好。
修改:这只是某些环境的问题,例如经典控件。
更新我
受到this的启发,我尝试了以下操作,而不是xvfb-run -s \"-screen 0 1400x900x24\" python <your_script.py>
(我无法开始工作)。
xvfb-run -a jupyter notebook
运行原始脚本我现在改为
GLXInfoException: pyglet requires an X server with GLX
更新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))
我得到ImportError: cannot import name gl_info
。
更新III
借助@ Torxed的灵感,我尝试创建一个视频文件,然后渲染它(一个完全令人满意的解决方案)。
使用“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()
我尝试了您的建议,但在运行ImportError: cannot import name gl_info
时获得了env.monitor.start(...
。
根据我的理解,问题是OpenAI使用pyglet
,而pyglet
'需要'一个屏幕,以便计算要渲染的图像的RGB颜色。 因此有必要欺骗python认为已连接监视器
更新IV
仅供参考,网上有使用大黄蜂的解决方案似乎有效。如果您可以控制服务器,这应该有效,但由于AWS在VM中运行,我认为您不能使用它。
更新V
如果您遇到此问题,并且不知道该怎么做(像我一样),大多数环境的状态都很简单,您可以创建自己的渲染机制。不太满意,但是......你知道。
答案 0 :(得分:22)
有一个简单的解决方案:
如果在linux服务器上,打开jupyter
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
在Jupyter
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.env
传递给show_state
。
答案 1 :(得分:10)
This 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()
使用mode='rgb_array'
会为您提供一个numpy.ndarray
,其中包含每个位置的RGB值,matplotlib
&#39; s imshow
(或其他方法)可以很好地显示这些值
请注意,如果您在同一单元格中渲染多次次,此解决方案每次都会绘制一个单独的图像。这可能不是你想要的。如果我找到一个好的解决方法,我会尝试更新它。
基于this 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)
答案 2 :(得分: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
用法:
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)
答案 3 :(得分:7)
我自己遇到了这个问题。
使用xvfb作为X服务器以某种方式与Nvidia驱动程序冲突。
但最后this帖子指出了我正确的方向。
如果使用-no-opengl-files
选项安装Nvidia驱动程序并使用--no-opengl-libs
选项安装CUDA,则Xvfb可以正常运行。
如果你知道这一点,它应该工作。但是因为我花了很长时间才弄清楚这一点,看起来我并不是唯一一个遇到xvfb和nvidia驱动程序问题的人。
我写下了使用Ubuntu 16.04 LTS here.
在AWS EC2实例上设置所有内容的所有必要步骤答案 4 :(得分:7)
我认为我们应该只使用OpenAI Gym wrappers.Monitor
将渲染捕获为视频
然后将其显示在笔记本中。
示例:
!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")
我希望它会有所帮助。 ;)
答案 5 :(得分:6)
还有this solution使用pyvirtualdisplay
(Xvfb包装器)。我喜欢这个解决方案的一件事是你可以从你的脚本中启动它,而不是在发布时包装它:
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
答案 6 :(得分:2)
我有同样的问题和I_like_foxes解决方案重新安装没有opengl修复的nvidia驱动程序。以下是我用于Ubuntu 16.04和GTX 1080ti的命令 https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78
答案 7 :(得分:2)
我通过简单地使用PIL,Python图像库来避免使用matplotlib的问题:
import gym, PIL
env = gym.make('SpaceInvaders-v0')
array = env.reset()
PIL.Image.fromarray(env.render(mode='rgb_array'))
我发现我不需要设置XV帧缓冲区。
答案 8 :(得分:1)
我一直在寻找一种可以在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:
您可以在Cartpole环境中使用xvfbwrapper。
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输出。
在Colab中,CommManager不可用。限制性更强的输出模块有一个名为eval_js()的方法,似乎有点慢。
答案 9 :(得分:1)
在这里参考我的其他答案:Display OpenAI gym in Jupyter notebook only
我在这里做了一个快速的示例,您可以使用它: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')))
如果您在具有公共访问权限的服务器上,则可以在Gym-results文件夹中运行python -m http.server
,然后在此处观看视频。
答案 10 :(得分:1)
This might be a complete workaround, but I used a docker image with a desktop environment, and it works great. The docker image is at 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.
Below are a gif showing it the Mario bros gym environment running and being rendered. As you can see, it is fairly responsive and smooth.
答案 11 :(得分:1)
我遇到了同样的问题,偶然发现了这里的答案。混合它们可以帮助我解决问题。
这是分步解决方案:
安装以下内容:
apt-get install -y python-opengl xvfb
通过以下命令启动jupyter笔记本:
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)
答案 12 :(得分:0)
在我的IPython环境中,Andrew Schreiber的解决方案无法平滑绘制图像。以下是我的解决方案:
如果在Linux服务器上,请使用以下命令打开jupyter:
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
在Jupyter中
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)
答案 13 :(得分:0)
我创建了这个mini-package,它允许您通过向代码中添加一行来将环境呈现到浏览器上。
将代码放入函数中,并用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()
,您将能够在浏览器窗口中看到渲染的环境。
答案 14 :(得分:0)