Подтвердить что ты не робот

Как запустить 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

Просто если у вас есть эта проблема, и вы не знаете, что делать (как и я), состояние большинства сред достаточно простое, чтобы вы могли создать свой собственный механизм рендеринга. Не очень приятно, но.. вы знаете.

4b9b3361

Ответ 1

Получено простое решение:

CartPole

Если на сервере 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.

Ответ 2

Мне удалось запустить и сделать 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)

Ответ 3

Я столкнулся с этим сам. Использование xvfb как X-сервера каким-то образом сталкивается с драйверами Nvidia. Но, наконец, этот поставил меня в правильном направлении. Xvfb работает без проблем, если вы устанавливаете драйвер Nvidia с опцией -no-opengl-files и CUDA с опцией --no-opengl-libs. Если вы это знаете, это должно сработать. Но поскольку мне потребовалось некоторое время, пока я не понял это, и похоже, что я не единственный, столкнувшийся с проблемами с xvfb и драйверами nvidia.

Я записал все необходимые шаги, чтобы установить все на экземпляре AWS EC2 с Ubuntu 16.04 LTS здесь.

Ответ 4

Этот вопрос 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 imshow (или другие методы) прекрасно их отображает.

Обратите внимание, что если вы рендерите несколько раз в одной и той же ячейке, это решение будет каждый раз отображать отдельное изображение. Это, вероятно, не то, что вы хотите. Я постараюсь обновить это, если я найду хороший обходной путь для этого.

Обновление для рендеринга несколько раз в одной ячейке

Основываясь на этом ответе StackOverflow, приведу рабочий фрагмент (обратите внимание, что могут быть более эффективные способы сделать это с помощью интерактивного графика; на моем компьютере этот способ выглядит немного запаздывающим):

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)

Ответ 5

Там также это решение, используя pyvirtualdisplay (обертка Xvfb). Одна вещь, которая мне нравится в этом решении, заключается в том, что вы можете запустить ее из своего script, вместо того, чтобы обернуть ее при запуске:

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

Ответ 6

Я избежал проблем с использованием 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.

Ответ 7

У меня была та же проблема и решение I_like_foxes для переустановки драйверов nvidia без каких-либо оппортунных вещей. Вот команды, которые я использовал для Ubuntu 16.04 и GTX 1080ti https://gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78

Ответ 8

Я думаю, что мы должны просто захватывать рендеры как видео с помощью 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")

Я надеюсь, что это помогает. ;)

Ответ 9

Я искал решение, которое работает в колаборатории, и закончилось этим

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(), который кажется довольно медленным.

Ответ 10

В моей среде 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)

Ответ 11

Ссылка на мой другой ответ здесь: Показать тренажерный зал 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 в папке результатов спортзала и просто посмотреть там видео.