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
.
Tuve el mismo problema y la misma solución de I_like_foxes para reinstalar los controladores de nvidia sin abrir cosas. Estos son los comandos que utilicé para Ubuntu 16.04 y GTX 1080ti https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78
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)