web-dev-qa-db-ja.com

サーバーでOpenAI Gym .render()を実行する方法

Jupyter(Ubuntu 14.04)を介して、p2.xlarge AWS サーバーでpython 2.7スクリプトを実行しています。シミュレーションをレンダリングできるようにしたいと思います。

最小限の作業例

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"

シミュレーションをどのように見ることができるかをいくつか教えてください。インラインで取得できれば理想的ですが、表示方法はどれでもいいでしょう。

Edit:これは、従来のコントロールなど、一部の環境での問題です。


更新I

this に触発された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はVMで実行されるため、これを使用できるとは思いません。


Vを更新

この問題があり、何をすべきかわからない場合(私のように)、ほとんどの環境の状態は単純で、独自のレンダリングメカニズムを作成できます。あまり満足できませんが、知っています。

48
Toke Faurby

簡単な解決策が得られました:

CartPole

$ 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.envshow_stateに渡します。

23

これ 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'を使用すると、各位置のRGB値を持つnumpy.ndarrayが返され、matplotlibimshow(または他のメソッド)はこれらを適切に表示します。

同じセルでmultiple回レンダリングする場合、このソリューションは毎回個別の画像をプロットすることに注意してください。これはおそらくあなたが望むものではありません。そのための適切な回避策を見つけた場合、これを更新しようとします。

1つのセルで複数回レンダリングするように更新する

this 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)
12
Nathan

ヘッドレスサーバーで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)
10
Van

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

役に立てば幸いです。 ;)

私は自分でこれに遭遇しました。 xvfbをXサーバーとして使用すると、どういうわけかNvidiaドライバーと競合します。しかし、最後に this postが正しい方向を示してくれました。 -no-opengl-filesオプションを使用してNvidiaドライバーをインストールし、--no-opengl-libsオプションを使用してCUDAをインストールすると、Xvfbは問題なく動作します。これを知っていれば、動作するはずです。しかし、これを理解するまでかなり時間がかかり、xvfbとnvidiaドライバーの問題に直面しているのは私だけではないようです。

Ubuntu 16.04 LTSを使用してAWS EC2インスタンスですべてをセットアップするために必要なすべての手順を書き留めました here。

7
I_like_foxes

このソリューションpyvirtualdisplay(Xvfbラッパー)を使用することもあります。このソリューションで気に入っている点の1つは、起動時にラップする代わりに、スクリプト内から起動できることです。

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

ここで他の答えを参照してください: JupyterノートブックのみにOpenAIジムを表示します

ここで、フォークできる簡単な作業例を作成しました: https://kyso.io/eoin/openai-gym-jupyter レンダリングの2つの例Jupyterで-1つはmp4として、もう1つはリアルタイム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')))

パブリックアクセスが可能なサーバーの場合は、gym-resultsフォルダーでpython -m http.serverを実行し、そこにあるビデオを見ることができます。

3
Eoin Murray

OpenGLを修正せずにnvidiaドライバーを再インストールするという同じ問題とI_like_foxesソリューションがありました。 Ubuntu 16.04およびGTX 1080tiに使用したコマンドは次のとおりです https://Gist.github.com/8enmann/931ec2a9dc45fde871d2139a7d1f2d78

2
Ben

PIL、Python Image Libraryを使用するだけで、matplotlibの使用に関する問題を回避しました。

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

XVフレームバッファーを設定する必要がないことがわかりました。

2
Doug Blank

Colaboratoryで機能するソリューションを探していましたが、最終的にはこれで終わりました

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:

Cartpole環境ではxvfbwrapperを使用できます。

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()と呼ばれるメソッドがありますが、これは少し遅いようです。

1
martinenzinger

これは完全な回避策かもしれませんが、デスクトップ環境でdockerイメージを使用しましたが、うまく機能します。 Dockerイメージは 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デスクトップにアクセスします。

以下は、マリオブラザーズのジム環境が実行されてレンダリングされている様子を示すgifです。ご覧のとおり、かなり反応がよく、スムーズです。

enter image description here

1
Costa Huang

私のIPython環境では、Andrew Schreiberのソリューションは画像をスムーズにプロットできません。以下は私の解決策です:

Linuxサーバーの場合、jupyterを開きます

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

Jupyterで

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)
0
Tom