webentwicklung-frage-antwort-db.com.de

So führen Sie OpenAI Gym .render () über einen Server aus

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.

43
Toke Faurby

Ich habe eine einfache Lösung, die funktioniert:

CartPole

$ 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.

19

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)
9
Van

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. matplotlibs 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.

Aktualisieren, um mehrere Male in einer Zelle zu rendern

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)

Update zur Steigerung der Effizienz

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)
8
Nathan

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.

7
I_like_foxes

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

Ich denke, wir sollten Rendern einfach als Video mit OpenAI Gym wrappers.Monitor Aufnehmen und dann im Notebook anzeigen.

Beispiel:

Abhängigkeiten

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

Als Video aufnehmen

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

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

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.

3
Doug Blank

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

2
Ben

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.

1
martinenzinger

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.

enter image description here

1
Costa Huang

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.

0
Eoin Murray

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)
0
Tom