Copyright 2021 Gli autori degli agenti TF.
Visualizza su TensorFlow.org | Esegui in Google Colab | Visualizza la fonte su GitHub | Scarica taccuino |
introduzione
Gli algoritmi di apprendimento del rinforzo utilizzano i buffer di riproduzione per memorizzare le traiettorie dell'esperienza durante l'esecuzione di una politica in un ambiente. Durante l'addestramento, i buffer di riproduzione vengono interrogati per un sottoinsieme delle traiettorie (un sottoinsieme sequenziale o un campione) per "riprodurre" l'esperienza dell'agente.
In questa collaborazione, esploriamo due tipi di replay buffer: supportati da Python e supportati da tensorflow, che condividono un'API comune. Nelle sezioni seguenti, descriviamo l'API, ciascuna delle implementazioni del buffer e come utilizzarle durante la formazione sulla raccolta dei dati.
Impostare
Installa tf-agent se non l'hai già fatto.
pip install 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
Replay Buffer API
La classe Replay Buffer ha la definizione e i metodi seguenti:
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"""
Si noti che quando l'oggetto buffer di riproduzione viene inizializzato, esso richiede la data_spec
degli elementi che memorizza. Questo spec corrisponde alla TensorSpec
di elementi traiettoria che verranno aggiunti al buffer. Questa specifica è generalmente acquisita, cercando in di un agente agent.collect_data_spec
che definisce le forme, i tipi e le strutture che ci si attende da parte dell'agente quando la formazione (ne riparleremo più avanti).
TFUniformReplayBuffer
TFUniformReplayBuffer
è il buffer di riproduzione più comunemente usato in TF-agenti, quindi useremo nel nostro tutorial qui. In TFUniformReplayBuffer
deposito del polmone supporto è fatto da variabili tensorflow e quindi è parte del grafico di calcolo.
I depositi intermedi lotti di elementi e ha un massimo capacità max_length
elementi per segmento batch. Pertanto, la capacità totale del buffer è batch_size
x max_length
elementi. Gli elementi archiviati nel buffer devono avere tutti una specifica di dati corrispondente. Quando il buffer di riproduzione viene utilizzato per la raccolta dei dati, la specifica è la specifica dei dati di raccolta dell'agente.
Creazione del buffer:
Per creare un TFUniformReplayBuffer
passiamo in:
- le specifiche degli elementi di dati che il buffer memorizzerà
- la
batch size
corrispondente alla dimensione del lotto di buffer - il
max_length
numero di elementi per segmento lotto
Ecco un esempio di creazione di un TFUniformReplayBuffer
con specifiche dati di esempio, batch_size
32 e 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)
Scrivendo nel buffer:
Per aggiungere elementi al buffer di riproduzione, usiamo add_batch(items)
metodo in cui items
è un elenco / tupla / nido del tensori rappresentativi del lotto di oggetti da aggiungere al buffer. Ogni elemento di items
deve avere una dimensione esterna uguale batch_size
e le dimensioni rimanenti deve rispettare le specifiche dati dell'elemento (stessi delle specifiche dati passati al costruttore buffer di riproduzione).
Ecco un esempio di aggiunta di un lotto di articoli
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)
Lettura dal buffer
Ci sono tre modi per leggere i dati dal TFUniformReplayBuffer
:
-
get_next()
- restituisce un campione dal buffer. La dimensione del batch di esempio e il numero di fasi temporali restituite possono essere specificati tramite argomenti a questo metodo. -
as_dataset()
- restituisce il buffer di riproduzione cometf.data.Dataset
. È quindi possibile creare un iteratore di set di dati e scorrere i campioni degli elementi nel buffer. -
gather_all()
- restituisce tutti gli articoli nel buffer come Tensor di forma[batch, time, data_spec]
Di seguito sono riportati esempi di come leggere dal buffer di riproduzione utilizzando ciascuno di questi metodi:
# 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 /tmp/ipykernel_15476/1348928897.py: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. WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/data/experimental/ops/counter.py:66: scan (from tensorflow.python.data.experimental.ops.scan_ops) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.data.Dataset.scan(...) 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 /tmp/ipykernel_15476/1348928897.py: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
ha la stessa functionaly come TFUniformReplayBuffer
ma invece di variabili tf, i dati vengono memorizzati in array numpy. Questo buffer può essere utilizzato per la raccolta di dati fuori dal grafico. Avere l'archiviazione di backup in numpy può rendere più semplice per alcune applicazioni la manipolazione dei dati (come l'indicizzazione per l'aggiornamento delle priorità) senza utilizzare le variabili Tensorflow. Tuttavia, questa implementazione non avrà il vantaggio delle ottimizzazioni del grafico con Tensorflow.
Di seguito è riportato un esempio di istanziare un PyUniformReplayBuffer
da specifiche politiche di traiettoria dell'agente:
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))
Utilizzo dei buffer di riproduzione durante l'allenamento
Ora che sappiamo come creare un buffer di replay, scriverci elementi e leggerlo, possiamo usarlo per memorizzare le traiettorie durante l'addestramento dei nostri agenti.
Raccolta dati
Innanzitutto, diamo un'occhiata a come utilizzare il buffer di riproduzione durante la raccolta dei dati.
Nel TF-Agenti usiamo un Driver
(vedi il tutorial driver per maggiori dettagli) per l'esperienza raccolta in un ambiente. Per utilizzare un Driver
, specifichiamo un Observer
che è una funzione per il Driver
da eseguire quando riceve una traiettoria.
Così, per aggiungere elementi traiettoria al buffer di riproduzione, si aggiunge un osservatore che chiamate add_batch(items)
per aggiungere un lotto di oggetti sul buffer di riproduzione.
Qui di seguito è un esempio di questo con TFUniformReplayBuffer
. Per prima cosa creiamo un ambiente, una rete e un agente. Poi creiamo un TFUniformReplayBuffer
. Notare che le specifiche degli elementi della traiettoria nel buffer di riproduzione sono uguali alle specifiche dei dati di raccolta dell'agente. Abbiamo poi impostato la sua add_batch
metodo come l'osservatore per il pilota che farà i dati raccolgono durante la nostra formazione:
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()
Lettura dei dati per un passaggio del treno
Dopo aver aggiunto elementi di traiettoria al buffer di replay, possiamo leggere batch di traiettorie dal buffer di replay da utilizzare come dati di input per una fase del treno.
Ecco un esempio di come allenarsi su traiettorie dal buffer di replay in un ciclo di allenamento:
# 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.7/site-packages/tensorflow/python/util/dispatch.py:206: 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))