Comment faire pour exécuter OpenAI salle de sport.render() sur un serveur

j'exécute un script python 2.7 sur un p2.xlarge AWS server through Jupyter (Ubuntu 14.04). J'aimerais pouvoir rendre mes simulations.

exemple de travail Minimal

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

env.render() fait (entre autres) les erreurs suivantes:

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

je voudrais être en mesure de voir les simulations. Il serait idéal si je pouvais obtenir en ligne, mais tout méthode d'affichage, ce serait bien.

Edit : C'est seulement un problème avec certains environnements, comme le contrôle classique.


Mise À Jour I

Inspiré par ce j'ai essayé les suivantes, au lieu du xvfb-run -s "-screen 0 1400x900x24" python <your_script.py> (que je ne pouvais pas aller au travail).

xvfb-run -a jupyter notebook

exécutant le script original je reçois maintenant au lieu de

GLXInfoException: pyglet requires an X server with GLX

mise à Jour II

Problème #154 semble pertinente. J'ai essayé de désactiver la pop-up, et de créer directement les couleurs 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)) 

je reçois ImportError: cannot import name gl_info .


mise à jour III

avec l'inspiration de @ Torxed j'ai essayé de créer un fichier vidéo, puis de le rendre (une solution entièrement satisfaisante).

utilisant le code de enregistrement et chargement des résultats

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

j'ai essayé de suivre vos suggestions, mais j'ai eu ImportError: cannot import name gl_info de quand j'ai lancé env.monitor.start(... .

D'après ce que j'ai compris, le problème est que OpenAI utilise pyglet , et pyglet a besoin d'un écran pour pour calculer les couleurs RVB de l'image qui doit être rendu. il faut donc tromper python pour penser qu'il y a un moniteur connecté


mise à jour IV

FYI il y a des solutions en ligne en utilisant bumblebee qui semblent fonctionner. Cela devrait fonctionner si vous avez le contrôle sur le serveur, mais depuis AWS exécuter dans une VM Je ne pense pas que vous pouvez utiliser cela.


Mise À Jour V

juste si vous avez ce problème, et ne savez pas quoi faire (comme moi) l'état de la plupart des environnements sont assez simple que vous pouvez créer votre propre mécanisme de rendu. Pas très satisfaisant, mais.. vous savez.

36
demandé sur Toke Faurby 2016-10-22 21:42:23

10 réponses

a Obtenu une solution simple de travail:

CartPole

Si sur un serveur linux, ouvrez jupyter avec
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
En Jupyter
import matplotlib.pyplot as plt
%matplotlib inline
from IPython import display
Après chaque étape
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: si votre environnement n'est pas unwrapped , passez env.env à show_state .

16
répondu Andrew Schreiber 2017-07-21 01:01:27

j'ai rencontré ça moi-même. L'utilisation de xvfb comme serveur X se heurte d'une manière ou d'une autre aux pilotes Nvidia. Mais finalement ce poteau m'a pointé dans la bonne direction. Xvfb fonctionne sans aucun problème si vous installez le pilote Nvidia avec l'option -no-opengl-files et CUDA avec l'option --no-opengl-libs . Si vous savez cela, il doit travailler. Mais comme il m'a fallu un certain temps jusqu'à ce que je m'en rende compte et il semble que je ne suis pas le seul à rencontrer des problèmes avec xvfb et le nvidia pilote.

j'ai noté toutes les étapes nécessaires pour tout mettre en place sur une instance AWS EC2 avec Ubuntu 16.04 LTS ici.

7
répondu I_like_foxes 2016-11-25 16:49:04

ce GitHub numéro a donné une réponse qui a fonctionné très bien pour moi. C'est bien parce qu'il ne nécessite pas de dépendances supplémentaires (je suppose que vous avez déjà matplotlib ) ou de configuration du serveur.

il suffit d'exécuter, par exemple:

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

en utilisant mode='rgb_array' vous donne en retour un numpy.ndarray avec les valeurs RGB pour chaque position, et matplotlib 's imshow (ou d'autres méthodes) affiche ces bien.

notez que si vous faites plusieurs fois dans la même cellule, Cette solution tracera une image séparée à chaque fois. Ce n'est probablement pas ce que vous voulez. Je vais essayer de mettre à jour si je l'ai trouver une bonne solution pour cela.

mise à Jour pour rendre plusieurs fois dans une cellule

basé sur ce réponse StackOverflow, voici un extrait de travail (Notez qu'il peut y avoir plus des façons efficaces de le faire avec une intrigue interactive; cette façon semble un peu lente sur ma machine):

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)

mise à jour pour augmenter l'efficacité

sur ma machine, c'était environ 3x plus rapide. La différence est qu'au lieu d'appeler imshow chaque fois que nous rendons, nous changeons simplement les données RGB sur le tracé original.

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)
6
répondu Nathan 2017-09-01 21:15:04

j'ai réussi à exécuter et à rendre openai/gym (même avec mujoco) à distance sur un serveur sans tête.

# 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

Utilisation:

DISPLAY=:0 ipython2

exemple:

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)
6
répondu Van 2018-01-13 05:34:13

il y a aussi cette solution en utilisant pyvirtualdisplay (une enveloppe Xvfb). Une chose que j'aime dans cette solution est que vous pouvez le lancer à partir de l'intérieur de votre script, au lieu d'avoir à l'envelopper au lancement:

from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
4
répondu mdaoust 2017-12-25 11:06:19

j'ai eu le même problème et I_like_foxes solution pour réinstaller les pilotes nvidia sans correction d'opengl. Voici les commandes que J'ai utilisées pour Ubuntu 16.04 et GTX 1080ti https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78

2
répondu Ben 2017-08-03 21:07:50

j'ai évité les problèmes avec l'utilisation de matplotlib en utilisant simplement PIL, Python Image Library:

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

j'ai trouvé que je n'avais pas besoin de régler le tampon du XV frame.

2
répondu Doug Blank 2018-01-08 00:27:46

je pense que nous devrions simplement capturer rend la vidéo en utilisant OpenAI salle de sport wrappers.Monitor et puis l'afficher à l'intérieur de l'ordinateur Portable.

exemple:

dépendances

!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 en vidéo

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

Afficher dans le bloc de 151990920"
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")

j'espère que ça aidera. ;)

2
répondu Trần Lê Thái Sơn 2018-07-05 07:49:01

dans mon environnement IPython, la solution D'Andrew Schreiber ne peut pas tracer l'image en douceur. Voici ma solution:

si sur un serveur linux, ouvrez jupyter avec

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

Dans Jupyter

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

affichage itération:

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
répondu Tom 2018-08-26 14:31:18

je cherchais une solution qui fonctionne en laboratoire et a fini avec ce

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

Afficher dans le Colaboratory

0
répondu martinenzinger 2018-09-22 17:43:42