Halaman ini diterjemahkan oleh Cloud Translation API.
Switch to English

Ulangi Buffer

Lihat di TensorFlow.org Jalankan di Google Colab Lihat sumber di GitHub Unduh buku catatan

pengantar

Algoritme pembelajaran penguatan menggunakan buffer replay untuk menyimpan lintasan pengalaman saat menjalankan kebijakan di suatu lingkungan. Selama pelatihan, buffer replay dikueri untuk subset dari lintasan (baik subset berurutan atau sampel) untuk "memutar ulang" pengalaman agen.

Dalam colab ini, kami menjelajahi dua jenis buffer replay: didukung python dan didukung tensorflow, berbagi API umum. Di bagian berikut, kami menjelaskan API, setiap implementasi buffer dan cara menggunakannya selama pelatihan pengumpulan data.

Mempersiapkan

Instal tf-agents jika Anda belum melakukannya.

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
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()

Putar Ulang Buffer API

Kelas Replay Buffer memiliki definisi dan metode berikut:

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"""

Perhatikan bahwa ketika objek buffer replay diinisialisasi, itu memerlukan data_spec dari elemen yang akan disimpannya. Spesifikasi ini sesuai dengan TensorSpec elemen lintasan yang akan ditambahkan ke buffer. Spesifikasi ini biasanya diperoleh dengan melihat agent.collect_data_spec agen yang mendefinisikan bentuk, tipe, dan struktur yang diharapkan oleh agen saat pelatihan (lebih lanjut tentang itu nanti)

TFUniformReplayBuffer

TFUniformReplayBuffer adalah buffer replay yang paling umum digunakan di TF-Agents, jadi kami akan menggunakannya dalam tutorial kami di sini. Dalam TFUniformReplayBuffer , penyimpanan backing buffer dilakukan oleh variabel tensorflow dan dengan demikian merupakan bagian dari grafik komputasi.

Buffer menyimpan kumpulan elemen dan memiliki kapasitas maksimum elemen max_length per segmen batch. Dengan demikian, total kapasitas buffer batch_size x max_length elemen. Semua elemen yang disimpan dalam buffer harus memiliki spesifikasi data yang cocok. Jika buffer replay digunakan untuk pengumpulan data, speknya adalah spek data kumpulkan agen.

Membuat buffer:

Untuk membuat TFUniformReplayBuffer kami TFUniformReplayBuffer :

  1. spesifikasi elemen data yang akan disimpan oleh buffer
  2. batch size sesuai dengan ukuran batch buffer
  3. jumlah max_length elemen per segmen batch

Berikut adalah contoh pembuatan TFUniformReplayBuffer dengan spesifikasi data sampel, batch_size 32 dan max_length 1000.

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)

Menulis ke buffer:

Untuk menambahkan elemen ke buffer replay, kami menggunakan metode add_batch(items) mana items adalah daftar / tuple / sarang tensor yang mewakili kumpulan item yang akan ditambahkan ke buffer. Setiap elemen items harus memiliki dimensi luar batch_size sama dan dimensi yang tersisa harus mematuhi spesifikasi data item (sama dengan spesifikasi data yang diteruskan ke konstruktor buffer replay).

Berikut adalah contoh menambahkan sekumpulan item

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)

Membaca dari buffer

Ada tiga cara untuk membaca data dari TFUniformReplayBuffer :

  1. get_next() - mengembalikan satu sampel dari buffer. Ukuran batch sampel dan jumlah langkah waktu yang dikembalikan dapat ditentukan melalui argumen untuk metode ini.
  2. as_dataset() - mengembalikan buffer replay sebagai tf.data.Dataset . Seseorang kemudian dapat membuat iterator set data dan melakukan iterasi melalui sampel item di buffer.
  3. gather_all() - mengembalikan semua item dalam buffer sebagai Tensor dengan bentuk [batch, time, data_spec]

Di bawah ini adalah contoh cara membaca dari replay buffer menggunakan masing-masing metode ini:

# 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 memiliki fungsi yang sama dengan TFUniformReplayBuffer tetapi sebagai ganti variabel tf, datanya disimpan dalam array numpy. Buffer ini dapat digunakan untuk pengumpulan data di luar grafik. Memiliki penyimpanan cadangan di numpy dapat mempermudah beberapa aplikasi untuk melakukan manipulasi data (seperti pengindeksan untuk memperbarui prioritas) tanpa menggunakan variabel Tensorflow. Namun, implementasi ini tidak akan mendapatkan manfaat dari pengoptimalan grafik dengan Tensorflow.

Di bawah ini adalah contoh instantiating PyUniformReplayBuffer dari spesifikasi lintasan kebijakan agen:

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))

Menggunakan buffer replay selama pelatihan

Sekarang kita tahu cara membuat buffer replay, menulis item ke sana dan membacanya, kita bisa menggunakannya untuk menyimpan lintasan selama pelatihan agen kita.

Pengumpulan data

Pertama, mari kita lihat cara menggunakan buffer replay selama pengumpulan data.

Di TF-Agents kami menggunakan Driver (lihat tutorial Driver untuk lebih jelasnya) untuk mengumpulkan pengalaman dalam suatu lingkungan. Untuk menggunakan Driver , kami menetapkan Observer yang merupakan fungsi untuk dijalankan Driver saat menerima lintasan.

Jadi, untuk menambahkan elemen lintasan ke buffer pemutaran ulang, kita menambahkan pengamat yang memanggil add_batch(items) untuk menambahkan (kumpulan) item pada buffer pemutaran ulang.

Di bawah ini adalah contohnya dengan TFUniformReplayBuffer . Pertama-tama kami membuat lingkungan, jaringan, dan agen. Kemudian kami membuat TFUniformReplayBuffer . Perhatikan bahwa spesifikasi elemen lintasan dalam buffer pemutaran ulang sama dengan spesifikasi data kumpulkan agen. Kami kemudian menetapkan metode add_batch sebagai pengamat untuk driver yang akan melakukan pengumpulan data selama pelatihan kami:

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))

Membaca data untuk langkah kereta

Setelah menambahkan elemen lintasan ke buffer pemutaran ulang, kita dapat membaca kumpulan lintasan dari buffer pemutaran ulang untuk digunakan sebagai data masukan untuk langkah kereta.

Berikut adalah contoh cara berlatih di lintasan dari buffer replay dalam loop pelatihan:

# 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)

WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/util/dispatch.py:201: calling foldr_v2 (from tensorflow.python.ops.functional_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.foldr(fn, elems, back_prop=False)
Use:
results = tf.nest.map_structure(tf.stop_gradient, tf.foldr(fn, elems))