openai open gym framework atari aigym python jupyter-notebook pyglet xvfb openai-gym

framework - openai gym python



Cómo ejecutar OpenAI Gym.render() en un servidor (9)

Estoy ejecutando un script de python 2.7 en un servidor AWS p2.xlarge a través de Jupyter (Ubuntu 14.04). Me gustaría poder hacer mis simulaciones.

Ejemplo de trabajo mínimo

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

env.render() hace (entre otras cosas) los siguientes errores:

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

Me gustaría de alguna forma poder ver las simulaciones. Sería ideal si pudiera ponerlo en línea, pero cualquier método de visualización sería agradable.

Editar : Esto es solo un problema con algunos entornos, como el control clásico.

Actualización I

Inspirado por this probé lo siguiente, en lugar de la xvfb-run -s /"-screen 0 1400x900x24/" python <your_script.py> (que no pude obtener para trabajar).

xvfb-run -a jupyter notebook

Ejecutando el script original ahora me sale

GLXInfoException: pyglet requires an X server with GLX

Actualización II

El problema #154 parece relevante. Intenté desactivar la ventana emergente y crear directamente los colores 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))

Obtengo ImportError: cannot import name gl_info .

Actualización III

Con la inspiración de @ Torxed intenté crear un archivo de video y luego renderizarlo (una solución totalmente satisfactoria).

Usando el código de '' Grabación y carga de resultados ''

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

Intenté seguir sus sugerencias, pero obtuve ImportError: cannot import name gl_info de al ejecutar env.monitor.start(...

Según tengo entendido, el problema es que OpenAI usa pyglet , y pyglet ''necesita'' una pantalla para calcular los colores RGB de la imagen que se va a renderizar. Por lo tanto, es necesario engañar a Python para que piense que hay un monitor conectado

Actualización IV

FYI hay soluciones en línea que usan abejorros que parecen funcionar. Esto debería funcionar si tienes control sobre el servidor, pero dado que AWS se ejecuta en una VM, no creo que puedas usar esto.

Actualización V

Solo si tiene este problema y no sabe qué hacer (como yo), el estado de la mayoría de los entornos es lo suficientemente simple como para que pueda crear su propio mecanismo de representación. No es muy satisfactorio, pero ... ya sabes.


Creo que deberíamos capturar renderizaciones como video utilizando OpenAI Gym wrappers.Monitor y luego mostrarlo en el Notebook.

Ejemplo:

Dependencias

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

Capturar como video

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

Mostrar dentro de 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")

Espero que ayude. ;)


En mi entorno IPython, la solución de Andrew Schreiber no puede trazar la imagen sin problemas. La siguiente es mi solución:

Si está en un servidor Linux, abra jupyter con

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

En Jupyter

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

Visualización de la pantalla:

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)


Evité los problemas con el uso de matplotlib simplemente usando PIL, Biblioteca de imágenes de Python:

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

Descubrí que no era necesario configurar el búfer de cuadros XV.


Logré correr y renderizar openai / gym (incluso con mujoco) de forma remota en un servidor sin cabeza.

# 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

Uso:

DISPLAY=:0 ipython2

Ejemplo:

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)


Me encontré con esto yo mismo. Usar xvfb como X-server de alguna manera choca con los controladores de Nvidia. Pero finalmente this post me indicó la dirección correcta. Xvfb funciona sin problemas si instala el controlador Nvidia con la opción -no-opengl-files y CUDA con la --no-opengl-libs . Si sabes esto, debería funcionar. Pero me tomó bastante tiempo hasta que descubrí esto y parece que no soy el único que tiene problemas con xvfb y los controladores de nvidia.

Anoté todos los pasos necesarios para configurar todo en una instancia de AWS EC2 con Ubuntu 16.04 LTS here.


También hay esta solución usando pyvirtualdisplay (un contenedor Xvfb). Una cosa que me gusta de esta solución es que puedes ejecutarla desde tu script, en lugar de tener que envolverlo en el lanzamiento:

from pyvirtualdisplay import Display display = Display(visible=0, size=(1400, 900)) display.start()


Tengo una solución simple trabajando:

Si está en un servidor Linux, abra jupyter con

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

import matplotlib.pyplot as plt %matplotlib inline from IPython import display Después de cada paso

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

Nota: si su entorno no está env.env , pase env.env a show_state .



This número de GitHub dio una respuesta que me funcionó muy bien. Es agradable porque no requiere ninguna dependencia adicional (supongo que ya tiene matplotlib ) o la configuración del servidor.

Solo ejecuta, por ejemplo:

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

El uso de mode=''rgb_array'' le devuelve un numpy.ndarray con los valores RGB para cada posición, y el matplotlib de imshow (u otros métodos) muestra estos muy bien.

Tenga en cuenta que si está renderizando varias veces en la misma celda, esta solución trazará una imagen separada cada vez. Esto probablemente no es lo que quieres. Intentaré actualizar esto si descubro una buena solución para eso.

Actualiza para renderizar varias veces en una celda

Basado en this respuesta de , aquí hay un fragmento de trabajo (tenga en cuenta que puede haber maneras más eficientes de hacer esto con un gráfico interactivo, de esta manera parece un poco lento en mi máquina):

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)

Actualización para aumentar la eficiencia

En mi máquina, esto fue aproximadamente 3 veces más rápido. La diferencia es que en lugar de llamar imshow cada vez que renderizamos, simplemente cambiamos los datos RGB en el diagrama 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)