このページは Cloud Translation API によって翻訳されました。
Switch to English

再生バッファ

TensorFlow.orgで見る Google Colabで実行 GitHubでソースを表示する ノートブックをダウンロード

前書き

強化学習アルゴリズムは、再生バッファーを使用して、環境でポリシーを実行するときの経験の軌跡を格納します。トレーニング中、エージェントのエクスペリエンスを「リプレイ」するために、リプレイバッファーにトラジェクトリのサブセット(シーケンシャルサブセットまたはサンプル)が照会されます。

このコラボでは、共通のAPIを共有する2種類のリプレイバッファー(python-backedとtensorflow-backed)を探索します。次のセクションでは、API、各バッファー実装、およびデータ収集トレーニング中にそれらを使用する方法について説明します。

セットアップ

tf-agentsをまだインストールしていない場合はインストールします。

pip install -q --pre tf-agents[reverb]
pip install -q gym
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

 from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
import numpy as np

from tf_agents import specs
from tf_agents.agents.dqn import dqn_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.networks import q_network
from tf_agents.replay_buffers import py_uniform_replay_buffer
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.specs import tensor_spec
from tf_agents.trajectories import time_step

tf.compat.v1.enable_v2_behavior()
 

再生バッファAPI

Replay Bufferクラスには、次の定義とメソッドがあります。

 class ReplayBuffer(tf.Module):
  """Abstract base class for TF-Agents replay buffer."""

  def __init__(self, data_spec, capacity):
    """Initializes the replay buffer.

    Args:
      data_spec: A spec or a list/tuple/nest of specs describing
        a single item that can be stored in this buffer
      capacity: number of elements that the replay buffer can hold.
    """

  @property
  def data_spec(self):
    """Returns the spec for items in the replay buffer."""

  @property
  def capacity(self):
    """Returns the capacity of the replay buffer."""

  def add_batch(self, items):
    """Adds a batch of items to the replay buffer."""

  def get_next(self,
               sample_batch_size=None,
               num_steps=None,
               time_stacked=True):
    """Returns an item or batch of items from the buffer."""

  def as_dataset(self,
                 sample_batch_size=None,
                 num_steps=None,
                 num_parallel_calls=None):
    """Creates and returns a dataset that returns entries from the buffer."""


  def gather_all(self):
    """Returns all the items in buffer."""
    return self._gather_all()

  def clear(self):
    """Resets the contents of replay buffer"""

 

再生バッファオブジェクトが初期化されるとき、それが格納する要素のdata_specが必要であることに注意してください。この仕様は、バッファーに追加される軌道要素のTensorSpecに対応しています。この仕様は通常、トレーニング時にエージェントが予期する形状、タイプ、および構造を定義するエージェントのagent.collect_data_specを調べることによって取得されます(詳細は後ほど)。

TFUniformReplayBuffer

TFUniformReplayBufferは、TF-Agentsで最も一般的に使用される再生バッファーであるため、ここのチュートリアルで使用します。 TFUniformReplayBuffer 、バッキングバッファーストレージはテンソルフロー変数によって行われるため、計算グラフの一部です。

バッファには要素のバッチが格納され、バッチセグメントごとに最大容量のmax_length要素があります。したがって、合計バッファ容量は、 batch_size x max_length要素です。バッファに格納される要素はすべて、一致するデータ仕様を持っている必要があります。再生バッファーがデータ収集に使用される場合、仕様はエージェントの収集データ仕様です。

バッファを作成する:

TFUniformReplayBufferを作成するには、 TFUniformReplayBufferように渡します。

  1. バッファが格納するデータ要素の仕様
  2. バッファのbatch size対応するバッチサイズ
  3. バッチセグメントごとの要素のmax_length

以下は、サンプルデータ仕様、 batch_size 32、 max_length 1000を使用してTFUniformReplayBufferを作成する例です。

 data_spec =  (
        tf.TensorSpec([3], tf.float32, 'action'),
        (
            tf.TensorSpec([5], tf.float32, 'lidar'),
            tf.TensorSpec([3, 2], tf.float32, 'camera')
        )
)

batch_size = 32
max_length = 1000

replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    data_spec,
    batch_size=batch_size,
    max_length=max_length)
 

バッファへの書き込み:

リプレイバッファに要素を追加するために、我々は、使用add_batch(items)メソッドitemsバッファに追加されるアイテムのバッチを表すテンソルのリスト/タプル/ネストです。 items各要素は、 batch_size等しい外側のディメンションを持っている必要があり、残りのディメンションはアイテムのデータ仕様に準拠している必要があります(再生バッファーコンストラクターに渡されるデータ仕様と同じ)。

アイテムのバッチを追加する例を次に示します

 action = tf.constant(1 * np.ones(
    data_spec[0].shape.as_list(), dtype=np.float32))
lidar = tf.constant(
    2 * np.ones(data_spec[1][0].shape.as_list(), dtype=np.float32))
camera = tf.constant(
    3 * np.ones(data_spec[1][1].shape.as_list(), dtype=np.float32))
  
values = (action, (lidar, camera))
values_batched = tf.nest.map_structure(lambda t: tf.stack([t] * batch_size),
                                       values)
  
replay_buffer.add_batch(values_batched)
 

バッファーからの読み取り

TFUniformReplayBufferからデータを読み取る方法は3つあります。

  1. get_next() -バッファから1つのサンプルを返します。返されるサンプルバッチサイズとタイムステップ数は、このメソッドの引数で指定できます。
  2. as_dataset() -再生バッファーをtf.data.Datasetとして返します。次に、データセットイテレータを作成し、バッファ内のアイテムのサンプルを反復処理できます。
  3. gather_all() -バッファ内のすべてのアイテムを、形状[batch, time, data_spec]テンソルとして返します

以下は、これらの各メソッドを使用して再生バッファーから読み取る方法の例です。

 # add more items to the buffer before reading
for _ in range(5):
  replay_buffer.add_batch(values_batched)

# Get one sample from the replay buffer with batch size 10 and 1 timestep:

sample = replay_buffer.get_next(sample_batch_size=10, num_steps=1)

# Convert the replay buffer to a tf.data.Dataset and iterate through it
dataset = replay_buffer.as_dataset(
    sample_batch_size=4,
    num_steps=2)

iterator = iter(dataset)
print("Iterator trajectories:")
trajectories = []
for _ in range(3):
  t, _ = next(iterator)
  trajectories.append(t)
  
print(tf.nest.map_structure(lambda t: t.shape, trajectories))

# Read all elements in the replay buffer:
trajectories = replay_buffer.gather_all()

print("Trajectories from gather all:")
print(tf.nest.map_structure(lambda t: t.shape, trajectories))

 
WARNING:tensorflow:From <ipython-input-6-1f9907631cb9>:7: ReplayBuffer.get_next (from tf_agents.replay_buffers.replay_buffer) is deprecated and will be removed in a future version.
Instructions for updating:
Use `as_dataset(..., single_deterministic_pass=False) instead.
Iterator trajectories:
[(TensorShape([4, 2, 3]), (TensorShape([4, 2, 5]), TensorShape([4, 2, 3, 2]))), (TensorShape([4, 2, 3]), (TensorShape([4, 2, 5]), TensorShape([4, 2, 3, 2]))), (TensorShape([4, 2, 3]), (TensorShape([4, 2, 5]), TensorShape([4, 2, 3, 2])))]
WARNING:tensorflow:From <ipython-input-6-1f9907631cb9>:24: ReplayBuffer.gather_all (from tf_agents.replay_buffers.replay_buffer) is deprecated and will be removed in a future version.
Instructions for updating:
Use `as_dataset(..., single_deterministic_pass=True)` instead.
Trajectories from gather all:
(TensorShape([32, 6, 3]), (TensorShape([32, 6, 5]), TensorShape([32, 6, 3, 2])))

PyUniformReplayBuffer

PyUniformReplayBuffer機能はTFUniformReplayBufferと同じTFUniformReplayBufferが、tf変数の代わりに、データはnumpy配列に格納されます。このバッファーは、グラフ外のデータ収集に使用できます。 numpyでバッキングストレージを使用すると、Tensorflow変数を使用せずに、一部のアプリケーションがデータ操作(優先度を更新するためのインデックス付けなど)を実行しやすくなります。ただし、この実装にはTensorflowによるグラフ最適化のメリットはありません。

以下は、エージェントのポリシー軌道仕様からPyUniformReplayBufferをインスタンス化する例です。

 replay_buffer_capacity = 1000*32 # same capacity as the TFUniformReplayBuffer

py_replay_buffer = py_uniform_replay_buffer.PyUniformReplayBuffer(
    capacity=replay_buffer_capacity,
    data_spec=tensor_spec.to_nest_array_spec(data_spec))
 

トレーニング中にリプレイバッファーを使用する

これで、リプレイバッファーを作成し、アイテムを書き込み、そこから読み取る方法がわかったので、エージェントのトレーニング中に軌跡を保存するために使用できます。

データ収集

まず、データ収集中にリプレイバッファーを使用する方法を見てみましょう。

TF-Agentsでは、 Driver (詳細についてはドライバーチュートリアルを参照)を使用して環境での経験を収集します。 Driverを使用するには、軌跡を受け取ったときにDriverが実行する関数であるObserverを指定します。

したがって、トラジェクトリ要素をリプレイバッファーに追加するには、 add_batch(items)を呼び出すオブザーバーを追加して、リプレイバッファーにアイテムの(バッチadd_batch(items)を追加します。

以下は、 TFUniformReplayBufferを使用したこの例です。まず、環境、ネットワーク、エージェントを作成します。次に、 TFUniformReplayBufferを作成しTFUniformReplayBuffer 。リプレイバッファー内の軌道要素の仕様は、エージェントの収集データ仕様と同じであることに注意してください。次に、そのadd_batchメソッドを、トレーニング中にデータ収集を行うドライバーのオブザーバーとして設定します。

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

q_net = q_network.QNetwork(
    tf_env.time_step_spec().observation,
    tf_env.action_spec(),
    fc_layer_params=(100,))

agent = dqn_agent.DqnAgent(
    tf_env.time_step_spec(),
    tf_env.action_spec(),
    q_network=q_net,
    optimizer=tf.compat.v1.train.AdamOptimizer(0.001))

replay_buffer_capacity = 1000

replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    agent.collect_data_spec,
    batch_size=tf_env.batch_size,
    max_length=replay_buffer_capacity)

# Add an observer that adds to the replay buffer:
replay_observer = [replay_buffer.add_batch]

collect_steps_per_iteration = 10
collect_op = dynamic_step_driver.DynamicStepDriver(
  tf_env,
  agent.collect_policy,
  observers=replay_observer,
  num_steps=collect_steps_per_iteration).run()
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tf_agents/drivers/dynamic_step_driver.py:203: calling while_loop_v2 (from tensorflow.python.ops.control_flow_ops) with back_prop=False is deprecated and will be removed in a future version.
Instructions for updating:
back_prop=False is deprecated. Consider using tf.stop_gradient instead.
Instead of:
results = tf.while_loop(c, b, vars, back_prop=False)
Use:
results = tf.nest.map_structure(tf.stop_gradient, tf.while_loop(c, b, vars))

電車のステップのデータを読み取る

トラジェクトリー要素をリプレイバッファーに追加した後、リプレイバッファーからトラジェクトリのバッチを読み取り、トレインステップの入力データとして使用できます。

以下は、トレーニングループでリプレイバッファーからの軌跡をトレーニングする方法の例です。

 # Read the replay buffer as a Dataset,
# read batches of 4 elements, each with 2 timesteps:
dataset = replay_buffer.as_dataset(
    sample_batch_size=4,
    num_steps=2)

iterator = iter(dataset)

num_train_steps = 10

for _ in range(num_train_steps):
  trajectories, _ = next(iterator)
  loss = agent.train(experience=trajectories)