Как запустить OpenAI Gym .render() на сервере
Я запускаю скрипт Python 2.7 на сервере AWS p2.xlarge через Jupyter (Ubuntu 14.04). Я хотел бы быть в состоянии сделать мои моделирования.
Минимальный рабочий пример
import gym
env = gym.make('CartPole-v0')
env.reset()
env.render()
env.render()
совершает (среди прочего) следующие ошибки:
...
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"
Я хотел бы, чтобы некоторые могли видеть симуляции. Было бы идеально, если бы я мог встроить его, но любой метод отображения был бы хорош.
Изменить: это проблема только в некоторых средах, таких как классический контроль.
Обновить я
Вдохновленный этим, я попробовал следующее, а не xvfb-run -s \"-screen 0 1400x900x24\" python <your_script.py>
(что я не мог добраться до работы).
xvfb-run -a jupyter notebook
Запустив оригинальный скрипт, я теперь получаю вместо
GLXInfoException: pyglet requires an X server with GLX
Обновление II
Вопрос № 154 представляется актуальным. Я попытался отключить всплывающее окно и напрямую создать цвета 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))
я получил ImportError: cannot import name gl_info
,
Обновление III
По вдохновению @ Torxed я попытался создать видеофайл, а затем воспроизвести его (полностью удовлетворяющее решение).
Использование кода из " Запись и загрузка результатов"
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()
Я пытался следовать вашим предложениям, но получил ImportError: cannot import name gl_info
с момента бега env.monitor.start(...
,
Насколько я понимаю, проблема в том, что OpenAI использует pyglet
, а также pyglet
"нужен" экран для вычисления цветов RGB изображения, которое должно быть отображено. Поэтому необходимо обмануть Python, чтобы думать, что подключен монитор
Обновление IV
К вашему сведению, есть онлайн решения с использованием шмеля, которые, кажется, работают. Это должно работать, если у вас есть контроль над сервером, но так как AWS работает на виртуальной машине, я не думаю, что вы можете использовать это.
Обновление V
Просто если у вас есть эта проблема, и вы не знаете, что делать (как и я), состояние большинства сред достаточно простое, чтобы вы могли создать свой собственный механизм рендеринга. Не очень приятно, но.. вы знаете.
10 ответов
Получил простое решение:
Если на сервере Linux, откройте Jupyter с$ 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())
Примечание: если ваша среда не unwrapped
, проходить env.env
в show_state
,
Этот вопрос GitHub дал ответ, который отлично сработал для меня. Это хорошо, потому что не требует никаких дополнительных зависимостей (я полагаю, у вас уже есть matplotlib
) или настройка сервера.
Просто беги, например:
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()
С помощью mode='rgb_array'
возвращает вам numpy.ndarray
со значениями RGB для каждой позиции, и matplotlib
"s imshow
(или другие методы) отображает это красиво.
Обратите внимание, что если вы рендерите несколько раз в одной и той же ячейке, это решение будет каждый раз отображать отдельное изображение. Это, вероятно, не то, что вы хотите. Я постараюсь обновить это, если я найду хороший обходной путь для этого.
Обновление для рендеринга несколько раз в одной ячейке
Основываясь на этом ответе Stackru, вот рабочий фрагмент (обратите внимание, что могут быть более эффективные способы сделать это с помощью интерактивного графика; этот способ выглядит немного запаздывающим на моей машине):
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)
Обновление для повышения эффективности
На моей машине это было примерно в 3 раза быстрее. Разница в том, что вместо вызова imshow
каждый раз, когда мы рендерим, мы просто меняем данные RGB на исходном графике.
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)
Я думаю, что мы должны просто захватывать рендеры как видео с помощью OpenAI Gym wrappers.Monitor
а затем отобразить его в блокноте.
Пример:
зависимости
!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")
Я надеюсь, что это помогает.;)
Мне удалось запустить и сделать openai/gym (даже с mujoco) удаленно на безголовом сервере.
# 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
Использование:
DISPLAY=:0 ipython2
Пример:
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)
Там также это решение с использованием pyvirtualdisplay
(Оболочка Xvfb). Что мне нравится в этом решении, так это то, что вы можете запустить его из своего скрипта, вместо того, чтобы оборачивать его при запуске:
from pyvirtualdisplay import Display
display = Display(visible=0, size=(1400, 900))
display.start()
Я столкнулся с этим сам. Использование xvfb в качестве X-сервера как-то конфликтует с драйверами Nvidia. Но, наконец, этот пост указал мне правильное направление.
Xvfb работает без проблем, если вы устанавливаете драйвер Nvidia с -no-opengl-files
вариант и CUDA с --no-opengl-libs
вариант. Если вы это знаете, это должно сработать. Но поскольку мне потребовалось довольно много времени, чтобы я это понял, и, похоже, я не единственный, у кого проблемы с драйверами xvfb и nvidia.
Я записал все необходимые шаги, чтобы настроить все на экземпляре AWS EC2 с Ubuntu 16.04 LTS здесь.
Я избежал проблем с использованием matplotlib, просто используя PIL, Python Image Library:
import gym, PIL
env = gym.make('SpaceInvaders-v0')
array = env.reset()
PIL.Image.fromarray(env.render(mode='rgb_array'))
Я обнаружил, что мне не нужно устанавливать буфер кадра XV.
Ссылка на мой другой ответ здесь: Показать тренажерный зал OpenAI только в блокноте Jupyter
Здесь я сделал быстрый рабочий пример, который вы могли бы разветвить: https://kyso.io/eoin/openai-gym-jupyter с двумя примерами рендеринга в Jupyter - один в виде mp4, а другой в виде GIF в реальном времени.
Пример.mp4 довольно прост.
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()
Затем в новой ячейке ячейки Jupyter или загрузите ее с сервера в какое-то место, где вы сможете просмотреть видео.
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')))
Если вы на сервере с публичным доступом, вы можете запустить python -m http.server
в папке результатов спортзала и просто смотрите видео там.
Я столкнулся с той же проблемой и наткнулся на ответы здесь. Их смешивание помогло мне решить проблему.
Вот пошаговое решение:
Установите следующее:
apt-get install -y python-opengl xvfb
Запустите записную книжку jupyter с помощью следующей команды:
xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
Внутри ноутбука:
import gym
import matplotlib.pyplot as plt
%matplotlib inline
env = gym.make('MountainCar-v0') # insert your favorite environment
env.reset()
plt.imshow(env.render(mode='rgb_array')
Теперь вы можете поместить одно и то же в цикл, чтобы отображать его несколько раз.
from IPython import display
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)
Надеюсь, это сработает для всех, кто все еще сталкивается с проблемой. Спасибо Эндрюсу и Натану за их ответы.
Я искал решение, которое работает в колаборатории, и закончилось этим
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')
РЕДАКТИРОВАТЬ 1:
Вы можете использовать xvfbwrapper для среды Cartpole.
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()
Если вы работаете со стандартным Jupyter, есть лучшее решение. Вы можете использовать CommManager для отправки сообщений с обновленными URL-адресами данных в ваш HTML-вывод.
Пример встроенного экрана IPython
В Colab CommManager недоступен. В более строгом модуле вывода есть метод eval_js(), который кажется довольно медленным.
У меня была такая же проблема и решение I_like_foxes для переустановки драйверов nvidia без каких-либо исправлений opengl. Вот команды, которые я использовал для Ubuntu 16.04 и GTX 1080ti https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78
Это может быть полный обходной путь, но я использовал образ докера со средой рабочего стола, и он отлично работает. Образ докера находится по адресу https://hub.docker.com/r/dorowu/ubuntu-desktop-lxde-vnc/
Команда для запуска
docker run -p 6080:80 dorowu/ubuntu-desktop-lxde-vnc
Затем просмотрите http://127.0.0.1:6080/ для доступа к рабочему столу Ubuntu.
Ниже приведен рисунок, показывающий, как работает тренажерный зал Mario Bros. Как видите, он довольно отзывчивый и плавный.
В моей среде IPython решение Эндрю Шрайбера не может плавно отображать изображение. Вот мое решение:
Если на сервере Linux, откройте Jupyter с
$ xvfb-run -s "-screen 0 1400x900x24" jupyter notebook
В Юпитере
import matplotlib.pyplot as plt
%matplotlib inline
%matplotlib notebook
from IPython import display
Отображение итерации:
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)
Я создал этот мини-пакет, который позволяет вам отображать вашу среду в браузере, просто добавив одну строку в ваш код.
Поместите свой код в функцию и замените обычный
env.render()
с участием
yield env.render(mode='rgb_array')
. Инкапсулируйте эту функцию с помощью
render_browser
декоратор.
import gym
from render_browser import render_browser
@render_browser
def test_policy(policy):
# Your function/code here.
env = gym.make('Breakout-v0')
obs = env.reset()
while True:
yield env.render(mode='rgb_array')
# ... run policy ...
obs, rew, _, _ = env.step(action)
test_policy(policy)
Когда вы посещаете
your_ip:5000
в вашем браузере,
test_policy()
будет вызван, и вы сможете увидеть визуализированную среду в окне браузера.