YutaroOgawa / Deep-Reinforcement-Learning-Book

書籍「つくりながら学ぶ!深層強化学習」のサポートリポジトリです
MIT License
339 stars 156 forks source link

3章P.79にて、動画の描画関数でTypeErrorが出ます。 #8

Open YutaroOgawa opened 4 years ago

YutaroOgawa commented 4 years ago

読者の方よりご質問いただきました。 誠にありがとうございます。

以下に詳細を記載しております。 どうぞよろしくお願い致します。

https://teratail.com/questions/250202

YutaroOgawa commented 4 years ago

読者の方よりいただきました。

cartpole の animation ですが、どうやら gym も最新版だと github で公開されている code で止まってしまうようです。 本で使われている 0.9.7 をインストールして動作することを確認しました。

mahha commented 4 years ago

お世話になっております。本書購入して勉強させて頂いています。

CartPoleの描画の件、自分もJSAnimationとmatplotlibの組み合わせで トラブったのですが、matplotlibに統合されている事が解りました。 一本化した方が何かとトラブりにくいかと思い、投稿します。

  1. JSAnimationは、matplotlib(2.1以降)に統合されたのでmatplotlibだけで良い
  2. 出力はインラインHTMLに変更する (コード後述)
  3. (Gym環境が生成する)謎のウィンドウはenv.close()で消せる (ウィンドウがハングする人向けです。困ってない人は気にしないで下さい)

環境: Win10Pro64bit Anaconda4.8.4 Python 3.7.4 final Gym 0.17.2 Matplotlib 3.2.2

参考URL: http://karel.tsuda.ac.jp/lec/python/matplotlib/anim/JSAnimation.html https://qiita.com/fhiyo/items/0ea94b0de6cd5c76d67a

長文で恐縮ですが、3-2のランダムカートポールの改変コード貼ります。 改変のポイントは以下です。

  1. animateにreturnを付ける
  2. display(display_animation ... のJSAnimation行は削除。
  3. 代わりにHTMLオブジェクト化してreturnする。呼び出し元でインライン表示させるため
import numpy as np
import matplotlib.pyplot as plt
import gym
%matplotlib inline
from IPython.display import HTML, display  ## *** HTMLもimport ***
from matplotlib import animation
def display_frames_as_gif(frames):
    """
    Displays a list of frames as a gif, with controls
    """

    fig = plt.figure(figsize=(frames[0].shape[1]/72.0, frames[0].shape[0]/72.0),dpi=72)
    patch = plt.imshow(frames[0])
    plt.axis('off')

    def animate(i):
        img = patch.set_data(frames[i])
        return img   ## *** returnが必要 ***

    anim = animation.FuncAnimation(plt.gcf(), animate, frames=len(frames), interval=50)

    anim.save('movie_cartpole.mp4')
    ## display(display_animation(anim, default_mode='loop'))  ## *** delete ***
    return HTML(anim.to_jshtml())  ## *** 呼び出し元で表示できるようにHTMLオブジェクトを返す ***
# ランダム動作

frames = []
env = gym.make('CartPole-v0')
observation = env.reset() # 最初は環境のリセットが必要

for step in range(0, 200):
    frames.append(env.render(mode='rgb_array'))
    action = np.random.choice(2) # 0:Left 1:Right をランダムに選ぶ
    observation, reward, done, info = env.step(action) # actionを環境に渡して実行

env.close()  ## *** さようなら、謎のウィンドウ ***
# 動画を保存と描画
html = display_frames_as_gif(frames) ## *** 描画結果をHTMLオブジェクトで取得する  ***
html ## *** IPython系でインラインHTML表示 ***
YutaroOgawa commented 4 years ago

@mahha さま

非常に丁寧に解決策をありがとうございます。

読者のみなさま、ぜひ上記いただいた改変版でも描画を試してみてください!

このように助けていただけ、私も多くの読者も助かります。誠にありがとうございます。