Ich führe ein Python 2.7-Skript auf einem p2.xlarge AWS -Server über Jupyter (Ubuntu 14.04) aus. Ich möchte meine Simulationen darstellen können.
Minimales Arbeitsbeispiel
import gym
env = gym.make('CartPole-v0')
env.reset()
env.render()
env.render()
macht (unter anderem) folgende Fehler:
...
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"
Ich würde gerne ein bisschen wissen, wie man die Simulationen sehen kann. Es wäre ideal, wenn ich es inline bekommen könnte, aber jede Anzeigemethode wäre Nizza.
Edit: Dies ist nur in einigen Umgebungen ein Problem, z. B. bei der klassischen Steuerung.
Update I
Inspiriert durch this habe ich Folgendes versucht, anstelle des xvfb-run -s \"-screen 0 1400x900x24\" python <your_script.py>
(den ich nicht zur Arbeit bekommen konnte).
xvfb-run -a jupyter notebook
Das ursprüngliche Skript ausführen, das ich jetzt bekomme
GLXInfoException: pyglet requires an X server with GLX
Update II
Ausgabe # 154 scheint relevant zu sein. Ich habe versucht, das Popup zu deaktivieren und die RGB-Farben direkt zu erstellen
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))
Ich bekomme ImportError: cannot import name gl_info
.
Update III
Mit der Inspiration von @ Torxed habe ich versucht, eine Videodatei zu erstellen und sie dann wiederzugeben (eine völlig zufriedenstellende Lösung).
Verwenden des Codes aus ' Ergebnisse aufzeichnen und hochladen '
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()
Ich habe versucht, Ihren Vorschlägen zu folgen, erhielt aber ImportError: cannot import name gl_info
von env.monitor.start(...
.
Nach meinem Verständnis besteht das Problem darin, dass OpenAI pyglet
verwendet und pyglet
einen Bildschirm benötigt, um die RGB-Farben des Bildes zu berechnen, das gerendert werden soll. Es ist daher notwendig, Python auszuliefern, um zu glauben, dass ein Monitor angeschlossen ist
Update IV
Zu Ihrer Information gibt es online Lösungen mit Hummel, die zu funktionieren scheinen. Dies sollte funktionieren, wenn Sie die Kontrolle über den Server haben. Da AWS jedoch in einer VM ausgeführt wird, glaube ich nicht, dass Sie dies verwenden können.
Update V
Nur wenn Sie dieses Problem haben und nicht wissen, was zu tun ist (wie ich), sind die meisten Umgebungen so einfach, dass Sie einen eigenen Rendering-Mechanismus erstellen können. Nicht sehr befriedigend, aber ... du weißt schon.
Ich habe eine einfache Lösung, die funktioniert:
$ 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())
Hinweis: Wenn Ihre Umgebung nicht unwrapped
ist, übergeben Sie env.env
an show_state
.
Ich habe es geschafft, Openai/Gym (auch mit Mujoco) auf einem Headless-Server remote auszuführen.
# 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
Verwendungszweck:
DISPLAY=:0 ipython2
Beispiel:
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)
Diese GitHub Ausgabe gab eine Antwort, die für mich gut funktionierte. Es ist nett, weil es keine zusätzlichen Abhängigkeiten (ich nehme an, Sie haben matplotlib
bereits) oder die Konfiguration des Servers an.
Einfach laufen lassen, z.
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()
Wenn Sie mode='rgb_array'
verwenden, erhalten Sie einen numpy.ndarray
mit den RGB-Werten für jede Position zurück. matplotlib
s imshow
(oder andere Methoden) zeigt diese gut an.
Wenn Sie mehrmals in derselben Zelle rendern, zeichnet diese Lösung jedes Mal ein separates Bild. Dies ist wahrscheinlich nicht das, was Sie wollen. Ich werde versuchen, das zu aktualisieren, wenn ich eine gute Lösung für das Problem finde.
Basierend auf this StackOverflow antworten, hier ein funktionierender Ausschnitt (Beachten Sie, dass es möglicherweise effizientere Möglichkeiten gibt, dies mit einem interaktiven Plot zu tun; dieser Weg scheint auf meinem Rechner etwas zu verzögern):
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)
Auf meinem Rechner war das etwa 3x schneller. Der Unterschied besteht darin, dass wir nicht jedes Mal, wenn wir rendern, imshow
aufrufen, sondern nur die RGB-Daten in der ursprünglichen Grafik ändern.
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)
Ich bin selbst darauf gestoßen. Wenn xvfb als X-Server verwendet wird, kollidiert es irgendwie mit den Nvidia-Treibern ..__ Aber schließlich this post zeigte mir in die richtige Richtung ..__ -no-opengl-files
Option und CUDA mit --no-opengl-libs
Option . Wenn Sie dies wissen, sollte es funktionieren. Aber es dauerte einige Zeit, bis ich das herausgefunden habe und es scheint, als wäre ich nicht der einzige, der Probleme mit xvfb und den nvidia-Treibern hat.
Ich habe alle notwendigen Schritte notiert, um alles auf einer AWS EC2-Instanz mit Ubuntu 16.04 LTS hier einzurichten.
Es gibt auch diese Lösung mit pyvirtualdisplay
(einem Xvfb-Wrapper). Eine Sache, die ich an dieser Lösung mag, ist, dass Sie sie von Ihrem Skript aus starten können, anstatt sie beim Start einzupacken:
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
Ich denke, wir sollten Rendern einfach als Video mit OpenAI Gym wrappers.Monitor
Aufnehmen und dann im Notebook anzeigen.
Beispiel:
!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")
Ich hoffe, es hilft. ;)
Ich habe die Probleme mit matplotlib vermieden, indem ich einfach PIL, Python Image Library verwendet habe:
import gym, PIL
env = gym.make('SpaceInvaders-v0')
array = env.reset()
PIL.Image.fromarray(env.render(mode='rgb_array'))
Ich stellte fest, dass ich den XV-Frame-Puffer nicht einstellen musste.
Ich hatte das gleiche Problem und eine I_like_foxes-Lösung, um nvidia-Treiber ohne Opengl-Fehler zu installieren. Hier sind die Befehle, die ich für Ubuntu 16.04 und GTX 1080ti verwendet habe https://Gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78
Ich suchte nach einer Lösung, die in Colaboratory funktioniert und damit endete
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:
Sie können xvfbwrapper für die Cartpole-Umgebung verwenden.
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()
Wenn Sie mit Standard-Jupyter arbeiten, gibt es jedoch eine bessere Lösung. Mit dem CommManager können Sie Nachrichten mit aktualisierten Daten-URLs an Ihre HTML-Ausgabe senden.
IPython Inline-Bildschirmbeispiel
In Colab ist der CommManager nicht verfügbar. Das restriktivere Ausgabemodul hat eine Methode namens eval_js (), die irgendwie langsam zu sein scheint.
Dies könnte eine vollständige Problemumgehung sein, aber ich habe ein Docker-Image mit einer Desktop-Umgebung verwendet und es funktioniert hervorragend. Das Docker-Image finden Sie unter https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc/
Der auszuführende Befehl lautet
docker run -p 6080:80 dorowu/ubuntu-desktop-lxde-vnc
Dann durchsuchen Sie http://127.0.0.1:6080/ , um auf den Ubuntu-Desktop zuzugreifen.
Unten sehen Sie ein GIF, das zeigt, wie die Mario bros-Fitnessumgebung ausgeführt und gerendert wird. Wie Sie sehen können, ist es ziemlich reaktionsschnell und reibungslos.
Verweis auf meine andere Antwort hier: Nur OpenAI-Fitnessstudio in Jupyter-Notebook anzeigen
Ich habe hier ein schnelles Arbeitsbeispiel gemacht, das Sie wie folgt zusammenfassen können: https://kyso.io/eoin/openai-gym-jupyter mit zwei Beispielen für das Rendern in Jupyter - eines als mp4 und eines als Echtzeit-GIF .
Das .mp4-Beispiel ist recht einfach.
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()
Dann in eine neue Jupyter-Zelle, oder lade sie vom Server an einen Ort, wo du das Video ansehen kannst.
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')))
Wenn Sie sich auf einem Server mit öffentlichem Zugriff befinden, können Sie python -m http.server
im Ordner Gym-Results ausführen und die Videos dort nur ansehen.
In meiner IPython-Umgebung kann die Lösung von Andrew Schreiber das Bild nicht reibungslos zeichnen. Das Folgende ist meine Lösung:
Wenn Sie sich auf einem Linux-Server befinden, öffnen Sie Jupyter mit
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
In Jupyter
import matplotlib.pyplot as plt
%matplotlib inline
%matplotlib notebook
from IPython import display
Iteration anzeigen:
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)