TF-Agents 0.4 Tutorials : REINFORCE エージェント (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 04/21/2020 (0.4)
* 本ページは、TF Agents の以下のドキュメントを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
REINFORCE エージェント
イントロダクション
このサンプルは TF-Agents ライブラリを使用してカートポール環境上 REINFORCE エージェントをどのように訓練するかを示します、DQN チュートリアル に似ています。
訓練、評価とデータ収集のための強化学習 (RL) パイプラインの総てのコンポーネントを通して貴方をガイドします。
セットアップ
以下の依存性をインストールしていないのであれば、次を実行します :
!sudo apt-get install -y xvfb ffmpeg !pip install 'gym==0.10.11' !pip install 'imageio==2.4.0' !pip install PILLOW !pip install 'pyglet==1.3.2' !pip install pyvirtualdisplay !pip install --upgrade tensorflow-probability !pip install tf-agents
from __future__ import absolute_import from __future__ import division from __future__ import print_function import base64 import imageio import IPython import matplotlib import matplotlib.pyplot as plt import numpy as np import PIL.Image import pyvirtualdisplay import tensorflow as tf from tf_agents.agents.reinforce import reinforce_agent from tf_agents.drivers import dynamic_step_driver from tf_agents.environments import suite_gym from tf_agents.environments import tf_py_environment from tf_agents.eval import metric_utils from tf_agents.metrics import tf_metrics from tf_agents.networks import actor_distribution_network from tf_agents.replay_buffers import tf_uniform_replay_buffer from tf_agents.trajectories import trajectory from tf_agents.utils import common tf.compat.v1.enable_v2_behavior() # Set up a virtual display for rendering OpenAI gym environments. display = pyvirtualdisplay.Display(visible=0, size=(1400, 900)).start()
ハイパーパラメータ
env_name = "CartPole-v0" # @param {type:"string"} num_iterations = 250 # @param {type:"integer"} collect_episodes_per_iteration = 2 # @param {type:"integer"} replay_buffer_capacity = 2000 # @param {type:"integer"} fc_layer_params = (100,) learning_rate = 1e-3 # @param {type:"number"} log_interval = 25 # @param {type:"integer"} num_eval_episodes = 10 # @param {type:"integer"} eval_interval = 50 # @param {type:"integer"}
環境
RL の環境は解こうとしているタスクや問題を表します。標準的な環境はスーツを使用して TF-Agents で容易に作成できます。文字列環境名が与えられたとき、OpenAI Gym, Atari, DM Control 等のようなソースから環境をロードするために様々なスーツを持ちます。
今は OpenAI Gym スーツからカートポール環境をロードしましょう。
env = suite_gym.load(env_name)
この環境をそれがどのようなものか見るためにレンダリングできます。free-swinging ポールはカートに装着されています。ゴールはポールを直立に維持するためにカートを右か左に動かすことです。
#@test {"skip": true} env.reset() PIL.Image.fromarray(env.render())
time_step = environment.step(action) ステートメントは環境でアクションを取ります。返される TimeStep タプルはそのアクションのための環境の次の観測と報酬を含みます。環境の time_step_spec() と action_spec() メソッドは time_step とアクションの仕様 (types, shapes, bounds) をそれぞれ返します。
print('Observation Spec:') print(env.time_step_spec().observation) print('Action Spec:') print(env.action_spec())
そして、観測は 4 floats の配列であることを見ます : カートの位置と速度、そしてポールの角度位置と角速度です。2 つのアクション (左に動かす or 右に動かす) だけが可能ですので、action_spec はスカラーでそこでは 0 は「左に動かす」を意味して 1 は「右に動かす」を意味します。
time_step = env.reset() print('Time step:') print(time_step) action = np.array(1, dtype=np.int32) next_time_step = env.step(action) print('Next time step:') print(next_time_step)
通常は 2 つの環境を作成します : 訓練のために一つと評価のために一つです。殆どの環境は純粋な python で書かれていますが、それらは TFPyEnvironment ラッパーを使用して容易に TensorFlow に変換できます。元の環境の API は numpy 配列を使用し、TFPyEnvironment はこれらを TensorFlow ポリシーとエージェントとより容易に相互作用するために貴方のために Tensor に/から変換します。
train_py_env = suite_gym.load(env_name) eval_py_env = suite_gym.load(env_name) train_env = tf_py_environment.TFPyEnvironment(train_py_env) eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)
エージェント
RL 問題を解くために使用するアルゴリズムはエージェントとして表されます。REINFORCE エージェントに加えて、TF-Agents は DQN, DDPG, TD3, PPO と SAC のような様々なエージェントの標準的な実装を提供します。
REINFORCE エージェントを作成するため、最初に Actor ネットワークを必要とします、これは環境からの観測が与えられたときアクションを予測することを学習できます。
観測とアクションの specs を使用して容易に Actor ネットワークを作成できます。ネットワークの層を指定できます、これは例えば各隠れ層のサイズを表す ints のタプルに設定される fc_layer_params 引数です (上のハイパーパラメータ・セクション参照)。
actor_net = actor_distribution_network.ActorDistributionNetwork( train_env.observation_spec(), train_env.action_spec(), fc_layer_params=fc_layer_params)
作成したばかりのネットワークを訓練するために optimizer と,ネットワークが何回更新されたかを追跡するための train_step_counter 変数もまた必要です。
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate) train_step_counter = tf.compat.v2.Variable(0) tf_agent = reinforce_agent.ReinforceAgent( train_env.time_step_spec(), train_env.action_spec(), actor_network=actor_net, optimizer=optimizer, normalize_returns=True, train_step_counter=train_step_counter) tf_agent.initialize()
ポリシー
TF-Agents では、ポリシーは RL のポリシーの標準的な概念を表します : time_step が与えられたときアクションかアクションに渡る分布を生成します。主要メソッドは policy_step = policy.step(time_step) です、そこでは policy_step は名前付きタプル PolicyStep(action, state, info) です。policy_step.action は環境に適用されるべきアクションで、state はステートフル (RNN) ポリシーのための状態を表して info はアクションの対数確率のような補助的情報を含むかもしれません。
エージェントは 2 つのポリシーを含みます : 主要ポリシーは評価/配備のため (agent.policy) に使用されてもう一つのポリシーはデータ収集のため (agent.collect_policy) に使用されます。
eval_policy = tf_agent.policy collect_policy = tf_agent.collect_policy
メトリクスと評価
ポリシーを評価するために使用される最も一般的なメトリックは平均リターンです。リターンはエピソードのための環境でポリシーを実行する間に得られた報酬の総計で、通常はこれを幾つかのエピソードに渡り平均します。次のように平均リターン・メトリックを計算できます。
def compute_avg_return(environment, policy, num_episodes=10): total_return = 0.0 for _ in range(num_episodes): time_step = environment.reset() episode_return = 0.0 while not time_step.is_last(): action_step = policy.action(time_step) time_step = environment.step(action_step.action) episode_return += time_step.reward total_return += episode_return avg_return = total_return / num_episodes return avg_return.numpy()[0] # Please also see the metrics module for standard implementations of different # metrics.
再生バッファ
環境から収集されたデータを追跡するために、TFUniformReplayBuffer を利用します。この再生バッファはストアされる tensor を記述する specs を使用して構築されます、これは tf_agent.collect_data_spec を使用してエージェントから得られます。
replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer( data_spec=tf_agent.collect_data_spec, batch_size=train_env.batch_size, max_length=replay_buffer_capacity)
殆どのエージェントについて、collect_data_spec は Trajectory と名前付けられたタプルで観測、アクション、報酬等を含みます。
データ収集
REINFORCE はエピソード全体から学習しますので、与えられたデータ収集ポリシーを使用してエピソードを集める関数を定義します、そしてデータ (観測、アクション、報酬等) を再生バッファの trajectories としてセーブします。
#@test {"skip": true} def collect_episode(environment, policy, num_episodes): episode_counter = 0 environment.reset() while episode_counter < num_episodes: time_step = environment.current_time_step() action_step = policy.action(time_step) next_time_step = environment.step(action_step.action) traj = trajectory.from_transition(time_step, action_step, next_time_step) # Add trajectory to the replay buffer replay_buffer.add_batch(traj) if traj.is_boundary(): episode_counter += 1 # This loop is so common in RL, that we provide standard implementations of # these. For more details see the drivers module.
エージェントを訓練する
訓練ループは環境からのデータ収集とエージェントのネットワークの最適化の両者を含みます。道中、どのようにやっているかを見るためにエージェントのポリシーを時々評価します。
以下は実行するために ~3 分かかります。
#@test {"skip": true} try: %%time except: pass # (Optional) Optimize by wrapping some of the code in a graph using TF function. tf_agent.train = common.function(tf_agent.train) # Reset the train step tf_agent.train_step_counter.assign(0) # Evaluate the agent's policy once before training. avg_return = compute_avg_return(eval_env, tf_agent.policy, num_eval_episodes) returns = [avg_return] for _ in range(num_iterations): # Collect a few episodes using collect_policy and save to the replay buffer. collect_episode( train_env, tf_agent.collect_policy, collect_episodes_per_iteration) # Use data from the buffer and update the agent's network. experience = replay_buffer.gather_all() train_loss = tf_agent.train(experience) replay_buffer.clear() step = tf_agent.train_step_counter.numpy() if step % log_interval == 0: print('step = {0}: loss = {1}'.format(step, train_loss.loss)) if step % eval_interval == 0: avg_return = compute_avg_return(eval_env, tf_agent.policy, num_eval_episodes) print('step = {0}: Average Return = {1}'.format(step, avg_return)) returns.append(avg_return)
可視化
プロット
エージェントのパフォーマンスを見るためにリターン vs グルーバルステップをプロットできます。Cartpole-v0 では、ポールが直立している総ての時間ステップについて環境は +1 の報酬を与えます、そしてステップの最大数は 200 ですから、最大の可能なリターンもまた 200 です。
#@test {"skip": true} steps = range(0, num_iterations + 1, eval_interval) plt.plot(steps, returns) plt.ylabel('Average Return') plt.xlabel('Step') plt.ylim(top=250)
ビデオ
各ステップで環境をレンダリングすることによりエージェントのパフォーマンスを可視化することは役立ちます。それを行なう前に、ビデオをこの colab に埋め込む関数を最初に作成しましょう。
def embed_mp4(filename): """Embeds an mp4 file in the notebook.""" video = open(filename,'rb').read() b64 = base64.b64encode(video) tag = ''' '''.format(b64.decode()) return IPython.display.HTML(tag)
以下のコードは幾つかのエピソードのためにエージェントのポリシーを可視化します :
num_episodes = 3 video_filename = 'imageio.mp4' with imageio.get_writer(video_filename, fps=60) as video: for _ in range(num_episodes): time_step = eval_env.reset() video.append_data(eval_py_env.render()) while not time_step.is_last(): action_step = tf_agent.policy.action(time_step) time_step = eval_env.step(action_step.action) video.append_data(eval_py_env.render()) embed_mp4(video_filename)
以上