Copyright 2018 The TF-Agents Authors.
TensorFlow.orgで表示 | Google Colabで実行 | GitHub でソースを表示{ | ノートブックをダウンロード/a0} |
はじめに
強化学習の一般的なパターンは、指定された数のステップまたはエピソードで環境でポリシーを実行することです。 これは、データ収集、評価、およびエージェントの動画の生成などの際に行われます。
Pythonでは比較的簡単に記述できますが、 tf.while
ループ、tf.cond
やtf.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