【強化学習】OpenAI GymのMonitorが非推奨に。代わりはRecordVideo
0. はじめに
以前Qiitaで、OpenAI GymをGoogle Colab上で描画する方法を投稿しました。
(ありがたいことに、書いた中で最もLGTMされた記事で、今でも時々LGTMが増えます。)
その中で紹介した3つの手法のうちの1つ(かつ実際に一番利用しそうな手法)である gym.wrappers.Monitor
を利用して mp4 ビデオとして保存する手法が、非推奨になっていることに気がついたので、その対処方法を調査しました。
1. 状況
2021年9月14日にリリースのGym 0.20.0より、gym.wrappers.Monitor
が非推奨になったと警告を表示するようになりました。
今は、まだ警告を表示するだけで、従来どおり gym.wrappers.Monitor
を利用することができますが、将来的には削除される可能性もあるため、推奨方法を調べました。
尚 gym.wrappers.Monitor
の非推奨化については、以下のissueで提案されています。
理由としてはビデオ録画だけでなく、統計情報(?)を併せて保存したりと多機能を詰め込んだ実装になっており、そのせいで done=True
じゃないと reset()
を呼べなかったりと使い勝手が悪くなっているので、新しくビデオ録画だけを切り取った実装に置き換えようということでした。
RecordVideo
2. 代替クラス: 非推奨化したgym.wrappers.Monitor
代わりに、gym.wrappers.RecordVideo
を使ってビデオを保存することができます。
使い方は、gym.wrappers.Monitor
とほとんど同じですが、一部コンストラクタの引数や仕様が変更になっています。
RecordVideo 引数 |
型 | 説明 | 対応するMonitor 引数 |
---|---|---|---|
env |
gym.Env |
ラップする環境 |
env (変更なし) |
video_folder |
str |
ビデオ保存フォルダ | directory |
episode_trigger = None |
Optional[Callable[[int], bool]] |
エピソードが記録対象か判断するための関数(None の時には1000エピソード毎、または1000未満の立法数( |
video_callable |
step_trigger = None |
Optional[Callable[[int], bool]] |
ステップが記録対象か判断するための関数 | (該当なし) |
video_length = 0 |
int | 記録するビデオの最大長(0 は制限なし) |
(該当なし) |
name_prefix = "rl-video" |
str |
記録するビデオ名の接頭辞 | (該当なし。モジュール変数 gym.wrappers.monitor.FILEPREFIX = "openaigym" で通常は固定) |
(Monitor
には他にも引数がありますが、機能整理したことでRecordVideo
には引き継がれませんでした。)
import gym
from gym.wrappers import ReordVideo
env = RecordVideo(gym.make("CartPole-v1"), "./")
o = env.reset()
for _ in range(100):
# step() の中で、自動的にビデオ録画されるため、 render() を明示的に呼ぶ必要はない。
o, r, d, _ = env.step(env.action_space.sample())
if d:
o = env.reset()
3. Google Colabで利用する場合
前のQiita記事と基本的には同じです。
仮想X11ディスプレイであるXvfbと、それをPythonから利用するためのPyVirtualDisplayをインストールを忘れないでください。
!apt update && apt install xvfb
!pip install pyvirtualdisplay
import base64
import io
import gym
from gym.wrappers import RecordVideo
from IPython import display
from pyvirtualdisplay import Display
d = Display()
d.start()
env = RecordVideo(gym.make('CartPole-v1'),'./')
o = env.reset()
for _ in range(100):
o, r, d, i = env.step(env.action_space.sample()) # 本当はDNNからアクションを入れる
if d:
env.reset()
for f in env.videos:
video = io.open(f[0], 'r+b').read()
encoded = base64.b64encode(video)
display.display(display.HTML(data="""
<video alt="test" controls>
<source src="data:video/mp4;base64,{0}" type="video/mp4" />
</video>
""".format(encoded.decode('ascii'))))
gnwrapper
) を使う場合
4. Gym-Notebook-Wrapper (以前作成して公開したGym-Notebook-Wrapperも更新して、v1.2.5
で RecordVideo
に対応しました。
(Google Colabにインストールされているバージョンが古い間は、あまり影響はないかもしれませんが、) インストールされているGymのバージョンがgym<=0.19.0
の時には、gym.wrappers.Monitor
を、gym>=0.20.0
の時には、gym.wrappers.RecordVideo
を利用するように処理を分けました。
(内部構造は色々変わっていたので、ちょっと面倒でした。)
!apt update && apt install xvfb
!pip install gym-notebook-wrapper
import gnwrapper
import gym
env = gnwrapper.Monitor(gym.make('CartPole-v1'),directory="./") # Xvfbが起動される
o = env.reset()
for _ in range(100):
o, r, d, i = env.step(env.action_space.sample()) # 本当はDNNからアクションを入れる
if d:
o = env.reset()
env.display() # ここで、ビデオとして保存した描画データを表示する
こちらは、両バージョンに対応するかつ互換性の観点から旧APIを維持しています。
引数 | 型 | 説明 |
---|---|---|
env |
gym.Env |
ラップされる環境 |
directory |
str |
ビデオを保存するフォルダ |
video_callable = None |
Optional[Callable[[int], bool]] |
エピソードが記録されるかを判断するための関数 |
*args / **kwargs
|
継承元のMonitor またはRecordVideo に渡される。(意図的に他の機能を利用する人は元の引数を調べているだろうので、差を吸収したりはしていません。) |
5. おわりに
OpenAI Gym のビデオ保存機能である gym.wrappers.Monitor
が非推奨になっていたので、後継の方法を調査しました。
また、Google ColabでOpenAI Gymを利用するために公開しているライブラリのGym-Notebook-Wrapperも対応しました。
Discussion