ドライバ

TensorFlow.orgで表示 Google Colabで実行 GitHub でソースを表示{ ノートブックをダウンロード/a0}

はじめに

強化学習の一般的なパターンは、指定された数のステップまたはエピソードで環境でポリシーを実行することです。 これは、データ収集、評価、およびエージェントの動画の生成などの際に行われます。

Pythonでは比較的簡単に記述できますが、 tf.whileループ、tf.condtf.control_dependenciesが含まれるため、TensorFlowでの記述やデバッグは非常に複雑になります。そのため、この実行ループの概念をdriverと呼ばれるクラスに抽象化する実装が提供されています。これはPythonとTensorFlowの両方で十分にテストされています。

さらに、各ステップでドライバに提供されるデータは、Trajectoryという名前のタプルに保存され、再生バッファーやメトリックなどのオブザーバーにブロードキャストされます。 このデータには、環境からの観察、ポリシーが推奨する行動、取得した報酬、その時点と次のステップのタイプなどが含まれます。

セットアップ

TF-agentまたはgymをまだインストールしていない場合は、以下を実行します。

pip install -q tf-agents
pip install -q gym
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf


from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.policies import random_py_policy
from tf_agents.policies import random_tf_policy
from tf_agents.metrics import py_metrics
from tf_agents.metrics import tf_metrics
from tf_agents.drivers import py_driver
from tf_agents.drivers import dynamic_episode_driver

tf.compat.v1.enable_v2_behavior()

Pythonドライバ

PyDriverクラスは、Python環境、Pythonポリシー、および各ステップで更新するオブザーバーのリストを受け取ります。主なメソッドはrun()で、終了基準(ステップ数がmax_steps に達するか、エピソード数がmax_episodesに達する)が少なくとも1つ満たされるまで、ポリシーに基づいた行動を環境で実行します。

大まかな実装は次のとおりです。

class PyDriver(object):

  def __init__(self, env, policy, observers, max_steps=1, max_episodes=1):
    self._env = env
    self._policy = policy
    self._observers = observers or []
    self._max_steps = max_steps or np.inf
    self._max_episodes = max_episodes or np.inf

  def run(self, time_step, policy_state=()):
    num_steps = 0
    num_episodes = 0
    while num_steps < self._max_steps and num_episodes < self._max_episodes:

      # Compute an action using the policy for the given time_step
      action_step = self._policy.action(time_step, policy_state)

      # Apply the action to the environment and get the next step
      next_time_step = self._env.step(action_step.action)

      # Package information into a trajectory
      traj = trajectory.Trajectory(
         time_step.step_type,
         time_step.observation,
         action_step.action,
         action_step.info,
         next_time_step.step_type,
         next_time_step.reward,
         next_time_step.discount)

      for observer in self._observers:
        observer(traj)

      # Update statistics to check termination
      num_episodes += np.sum(traj.is_last())
      num_steps += np.sum(~traj.is_boundary())

      time_step = next_time_step
      policy_state = action_step.state

    return time_step, policy_state

次に、CartPole環境でランダムポリシーを実行し、結果を再生バッファーに保存し、いくつかのメトリックを計算する例を見てみましょう。

env = suite_gym.load('CartPole-v0')
policy = random_py_policy.RandomPyPolicy(time_step_spec=env.time_step_spec(), 
                                         action_spec=env.action_spec())
replay_buffer = []
metric = py_metrics.AverageReturnMetric()
observers = [replay_buffer.append, metric]
driver = py_driver.PyDriver(
    env, policy, observers, max_steps=20, max_episodes=1)

initial_time_step = env.reset()
final_time_step, _ = driver.run(initial_time_step)

print('Replay Buffer:')
for traj in replay_buffer:
  print(traj)

print('Average Return: ', metric.result())
Replay Buffer:
Trajectory(step_type=array(0, dtype=int32), observation=array([-0.04771208,  0.01992483,  0.04498768,  0.01212078], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04731358, -0.17581247,  0.0452301 ,  0.3186516 ], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.05082983,  0.0186371 ,  0.05160313,  0.04056865], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.05045709,  0.21298255,  0.0524145 , -0.23539689], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04619744,  0.01715243,  0.04770656,  0.07334769], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04585439,  0.21155915,  0.04917352, -0.20391019], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04162321,  0.01576971,  0.04509531,  0.10387015], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04130781, -0.17996852,  0.04717272,  0.41043252], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04490718,  0.01445403,  0.05538137,  0.13298677], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.0446181 ,  0.20874076,  0.0580411 , -0.14172271], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.04044329,  0.40298548,  0.05520665, -0.41554466], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.03238358,  0.5972833 ,  0.04689576, -0.69032484], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.02043791,  0.40154305,  0.03308926, -0.383255  ], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.01240705,  0.59617996,  0.02542416, -0.6653241 ], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([-0.00048345,  0.40071377,  0.01211768, -0.36474565], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([ 0.00753082,  0.20542173,  0.00482276, -0.06826656], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([0.01163926, 0.01023096, 0.00345743, 0.22593406], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([ 0.01184388, -0.18494023,  0.00797611,  0.5197056 ], dtype=float32), action=array(1), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([0.00814507, 0.01006853, 0.01837023, 0.2295467 ], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Trajectory(step_type=array(1, dtype=int32), observation=array([ 0.00834644, -0.18531105,  0.02296116,  0.52796715], dtype=float32), action=array(0), policy_info=(), next_step_type=array(1, dtype=int32), reward=array(1., dtype=float32), discount=array(1., dtype=float32))
Average Return:  0.0

TensorFlowドライバ

また、TensorFlowには、Pythonドライバと機能的に似ているドライバがありますが、TensorFlowドライバでは、TF環境、TFポリシー、TFオブザーバーなどを使用します。現在、次の2つのTensorFlowドライバがあります。DynamicStepDriverは、指定された数の(有効な)環境ステップの後に終了します。DynamicEpisodeDriver、指定された数のエピソードの後に終了します。 では、実際のDynamicEpisodeの例を見てみましょう。

env = suite_gym.load('CartPole-v0')
tf_env = tf_py_environment.TFPyEnvironment(env)

tf_policy = random_tf_policy.RandomTFPolicy(action_spec=tf_env.action_spec(),
                                            time_step_spec=tf_env.time_step_spec())


num_episodes = tf_metrics.NumberOfEpisodes()
env_steps = tf_metrics.EnvironmentSteps()
observers = [num_episodes, env_steps]
driver = dynamic_episode_driver.DynamicEpisodeDriver(
    tf_env, tf_policy, observers, num_episodes=2)

# Initial driver.run will reset the environment and initialize the policy.
final_time_step, policy_state = driver.run()

print('final_time_step', final_time_step)
print('Number of Steps: ', env_steps.result().numpy())
print('Number of Episodes: ', num_episodes.result().numpy())
final_time_step TimeStep(step_type=<tf.Tensor: shape=(1,), dtype=int32, numpy=array([0], dtype=int32)>, reward=<tf.Tensor: shape=(1,), dtype=float32, numpy=array([0.], dtype=float32)>, discount=<tf.Tensor: shape=(1,), dtype=float32, numpy=array([1.], dtype=float32)>, observation=<tf.Tensor: shape=(1, 4), dtype=float32, numpy=
array([[-0.02567231,  0.01213858,  0.01792433, -0.03394789]],
      dtype=float32)>)
Number of Steps:  58
Number of Episodes:  2
# Continue running from previous state
final_time_step, _ = driver.run(final_time_step, policy_state)

print('final_time_step', final_time_step)
print('Number of Steps: ', env_steps.result().numpy())
print('Number of Episodes: ', num_episodes.result().numpy())
final_time_step TimeStep(step_type=<tf.Tensor: shape=(1,), dtype=int32, numpy=array([0], dtype=int32)>, reward=<tf.Tensor: shape=(1,), dtype=float32, numpy=array([0.], dtype=float32)>, discount=<tf.Tensor: shape=(1,), dtype=float32, numpy=array([1.], dtype=float32)>, observation=<tf.Tensor: shape=(1, 4), dtype=float32, numpy=
array([[-0.03832928,  0.0018736 ,  0.00529633,  0.02694627]],
      dtype=float32)>)
Number of Steps:  127
Number of Episodes:  4