Tarihi kaydet! Google I / O 18-20 Mayıs'ta geri dönüyor Şimdi kaydolun
Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Yeniden Oynatma Tamponları

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Defteri indirin

Giriş

Takviye öğrenme algoritmaları, bir ortamda bir ilkeyi uygularken deneyim yörüngelerini depolamak için tekrar arabellekleri kullanır. Eğitim sırasında, yeniden oynatma arabellekleri, aracının deneyimini "yeniden oynatmak" için yörüngelerin bir alt kümesi (sıralı bir alt küme veya bir örnek) için sorgulanır.

Bu çalışmada, ortak bir API paylaşan python destekli ve tensorflow destekli olmak üzere iki tür yeniden oynatma tamponunu keşfediyoruz. Aşağıdaki bölümlerde, API'yi, tampon uygulamalarının her birini ve veri toplama eğitimi sırasında bunların nasıl kullanılacağını açıklıyoruz.

Kurulum

Henüz yapmadıysanız tf-agent'ları kurun.

pip install -q tf-agents
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()

Replay Buffer API

Replay Buffer sınıfı aşağıdaki tanım ve yöntemlere sahiptir:

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

Yeniden yürütme arabelleği nesnesi başlatıldığında, depolayacağı öğelerin data_spec gerektirdiğine dikkat edin. Bu belirtim, arabelleğe eklenecek yörünge öğelerinin TensorSpec karşılık gelir. Bu özellik, genellikle bir temsilcinin eğitim sırasında temsilcinin beklediği şekilleri, türleri ve yapıları tanımlayan agent.collect_data_spec bakılarak elde edilir (bundan sonra daha fazlası).

TFUniformReplayBuffer

TFUniformReplayBuffer , TF-Agent'larda en sık kullanılan yeniden oynatma arabelleğidir, bu nedenle TFUniformReplayBuffer kullanacağız. TFUniformReplayBuffer arka tampon depolaması tensorflow değişkenleri tarafından yapılır ve bu nedenle hesaplama grafiğinin bir parçasıdır.

Tampon, öğe gruplarını depolar ve parti segmenti başına maksimum kapasite max_length öğelerine sahiptir. Bu durumda, toplam ara bellek kapasitesi batch_size x max_length elemanları. Arabellekte depolanan öğelerin tümü, eşleşen bir veri spesifikasyonuna sahip olmalıdır. Veri toplama için yeniden oynatma arabelleği kullanıldığında, özellik, aracının veri toplama özelliğidir.

Tamponun oluşturulması:

Bir TFUniformReplayBuffer oluşturmak için TFUniformReplayBuffer :

  1. arabelleğin saklayacağı veri öğelerinin özellikleri
  2. tamponun batch size karşılık gelen parti boyutu
  3. parti segmenti başına max_length eleman sayısı

Burada oluşturma örneğidir TFUniformReplayBuffer örnek veri özellikleri ile batch_size 32 ve max_length 1000 civarındadır.

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)

Arabelleğe yazılıyor:

Tekrar tampon elemanları eklemek için, kullandığımız add_batch(items) yöntemi items öğe toplu temsil tensörlerinin bir liste / demet / yuva tamponuna ilave edilir. items her bir öğesinin batch_size değerine eşit bir dış boyutu olmalıdır ve kalan boyutlar öğenin veri spesifikasyonuna uymalıdır (yeniden oynatma tamponu yapıcısına iletilen veri özellikleriyle aynı).

İşte bir grup öğe eklemenin bir örneği

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)

Tampondan okuma

TFUniformReplayBuffer veri okumanın üç yolu vardır:

  1. get_next() - tampondan bir örnek döndürür. Örnek parti boyutu ve döndürülen zaman adımı sayısı, bu yönteme argümanlar aracılığıyla belirtilebilir.
  2. as_dataset() - yeniden oynatma arabelleğinitf.data.Dataset olarak döndürür. Daha sonra bir veri kümesi yineleyicisi oluşturulabilir ve arabellekteki öğelerin örnekleri arasında yineleme yapılabilir.
  3. gather_all() - arabellekteki tüm öğeleri [batch, time, data_spec] şeklinde bir Tensör olarak döndürür

Aşağıda, bu yöntemlerin her biri kullanılarak yeniden oynatma arabelleğinden nasıl okunacağına dair örnekler verilmiştir:

# 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-1-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-1-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 aynı fonksiyonel olarak var TFUniformReplayBuffer yerine tf değişkenler, veri numpy diziler depolanır. Bu arabellek, grafik dışı veri toplama için kullanılabilir. Yedek depolamanın numpy'de olması, bazı uygulamaların Tensorflow değişkenleri kullanmadan veri işleme (öncelikleri güncellemek için dizin oluşturma gibi) yapmasını kolaylaştırabilir. Ancak, bu uygulama Tensorflow ile grafik optimizasyonlarından yararlanamayacak.

Aşağıda, aracının politika yörünge özelliklerinden bir PyUniformReplayBuffer örneğini oluşturmaya bir örnek verilmiştir:

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

Eğitim sırasında yeniden oynatma tamponlarını kullanma

Artık bir tekrar tamponu oluşturmayı, ona öğeler yazmayı ve ondan okumayı bildiğimize göre, aracılarımızın eğitimi sırasında yörüngeleri depolamak için kullanabiliriz.

Veri toplama

İlk olarak, veri toplama sırasında yeniden oynatma arabelleğinin nasıl kullanılacağına bakalım.

TF-Agent'larda, bir ortamda deneyim toplamak için bir Driver (daha fazla ayrıntı için Sürücü eğitimine bakın) kullanıyoruz. Bir Driver kullanmak için, Driver bir yörünge aldığında yürüteceği bir işlev olan bir Observer belirtiriz.

Bu nedenle, yeniden oynatma arabelleğine yörünge öğeleri eklemek için, yeniden oynatma arabelleğine bir grup öğe eklemek için add_batch(items) i çağıran bir gözlemci add_batch(items) .

Aşağıda TFUniformReplayBuffer ile TFUniformReplayBuffer bir örneğini TFUniformReplayBuffer . Önce bir ortam, bir ağ ve bir ajan oluşturuyoruz. Sonra bir TFUniformReplayBuffer oluşturuyoruz. Tekrar arabelleğindeki yörünge öğelerinin özelliklerinin, aracının veri toplama özelliğine eşit olduğuna dikkat edin. Ardından, add_batch sırasında verileri toplayacak sürücü için gözlemci olarak add_batch yöntemini belirledik:

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

Bir tren adımı için verileri okuma

Tekrar arabelleğine yörünge öğeleri ekledikten sonra, bir tren adımı için girdi verisi olarak kullanmak üzere tekrar arabelleğinden yörünge gruplarını okuyabiliriz.

Aşağıda, bir eğitim döngüsündeki tekrar arabelleğinden yörüngeler üzerinde nasıl eğitim yapılacağına dair bir örnek verilmiştir:

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