Copyright 2021 Gli autori degli agenti TF.
Visualizza su TensorFlow.org | Esegui in Google Colab | Visualizza la fonte su GitHub | Scarica taccuino |
introduzione
In questa collaborazione tratteremo come definire reti personalizzate per i tuoi agenti. Le reti ci aiutano a definire il modello che viene addestrato dagli agenti. In TF-Agents troverai diversi tipi di reti utili tra gli agenti:
Reti principali
- QNetwork: Utilizzato in Qlearning per ambienti con azioni discrete, questa rete associa un'osservazione per le stime di valore per ogni possibile azione.
- CriticNetworks: Indicato anche come
ValueNetworks
nella letteratura, impara a stimare una qualche versione di una funzione di valore mappare qualche stato in una stima per il rendimento atteso di una politica. Queste reti stimano lo stato in cui si trova attualmente l'agente. - ActorNetworks: Imparare una mappatura dalle osservazioni alle azioni. Queste reti vengono solitamente utilizzate dalle nostre norme per generare azioni.
- ActorDistributionNetworks: simili
ActorNetworks
ma questi generano una distribuzione che una politica può allora campione per generare azioni.
Reti di aiuto
- EncodingNetwork: Consente agli utenti di definire facilmente una mappatura dei livelli pre-elaborazione per applicare all'ingresso di una rete.
- DynamicUnrollLayer: reimposta automaticamente lo stato della rete sui confini episodio come viene applicato su una sequenza temporale.
- ProjectionNetwork: Le reti come
CategoricalProjectionNetwork
oNormalProjectionNetwork
prendono ingressi e generano i parametri necessari per generare categoriali, o distribuzioni normali.
Tutti gli esempi in TF-Agents sono forniti con reti preconfigurate. Tuttavia queste reti non sono configurate per gestire osservazioni complesse.
Se hai un ambiente che espone più di un'osservazione/azione e hai bisogno di personalizzare le tue reti, questo tutorial fa per te!
Impostare
Se non hai ancora installato tf-agent, esegui:
pip install tf-agents
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import abc
import tensorflow as tf
import numpy as np
from tf_agents.environments import random_py_environment
from tf_agents.environments import tf_py_environment
from tf_agents.networks import encoding_network
from tf_agents.networks import network
from tf_agents.networks import utils
from tf_agents.specs import array_spec
from tf_agents.utils import common as common_utils
from tf_agents.utils import nest_utils
Definizione di reti
API di rete
Nel TF-Agenti abbiamo sottoclasse da Keras Networks . Con esso possiamo:
- Semplifica le operazioni di copia richieste durante la creazione di reti di destinazione.
- Eseguire la creazione automatica variabile quando si chiama
network.variables()
. - Convalida gli input in base a input_specs di rete.
Rete di codifica
Come accennato in precedenza EncodingNetwork
permette di definire facilmente una mappatura di strati di pre-elaborazione per applicare all'ingresso di una rete per generare qualche codifica.
La EncodingNetwork è composta dai seguenti livelli per lo più opzionali:
- Strati di pre-elaborazione
- Combinatore di pre-elaborazione
- Conv2D
- Appiattire
- Denso
La particolarità della codifica delle reti è che viene applicata la preelaborazione dell'input. Pre-elaborazione di ingresso è possibile tramite preprocessing_layers
e preprocessing_combiner
strati. Ognuno di questi può essere specificato come una struttura nidificata. Se il preprocessing_layers
nido è meno profonda input_tensor_spec
, quindi gli strati sarà possibile ottenere il subnests. Ad esempio, se:
input_tensor_spec = ([TensorSpec(3)] * 2, [TensorSpec(3)] * 5)
preprocessing_layers = (Layer1(), Layer2())
quindi la pre-elaborazione chiamerà:
preprocessed = [preprocessing_layers[0](observations[0]),
preprocessing_layers[1](observations[1])]
Tuttavia se
preprocessing_layers = ([Layer1() for _ in range(2)],
[Layer2() for _ in range(5)])
quindi la pre-elaborazione chiamerà:
preprocessed = [
layer(obs) for layer, obs in zip(flatten(preprocessing_layers),
flatten(observations))
]
Reti personalizzate
Per creare le proprie reti si avrà solo per sostituire le __init__
e call
metodi. Creiamo una rete personalizzata utilizzando quello che abbiamo imparato a conoscere EncodingNetworks
per creare un ActorNetwork che prende le osservazioni che contengono un'immagine e un vettore.
class ActorNetwork(network.Network):
def __init__(self,
observation_spec,
action_spec,
preprocessing_layers=None,
preprocessing_combiner=None,
conv_layer_params=None,
fc_layer_params=(75, 40),
dropout_layer_params=None,
activation_fn=tf.keras.activations.relu,
enable_last_layer_zero_initializer=False,
name='ActorNetwork'):
super(ActorNetwork, self).__init__(
input_tensor_spec=observation_spec, state_spec=(), name=name)
# For simplicity we will only support a single action float output.
self._action_spec = action_spec
flat_action_spec = tf.nest.flatten(action_spec)
if len(flat_action_spec) > 1:
raise ValueError('Only a single action is supported by this network')
self._single_action_spec = flat_action_spec[0]
if self._single_action_spec.dtype not in [tf.float32, tf.float64]:
raise ValueError('Only float actions are supported by this network.')
kernel_initializer = tf.keras.initializers.VarianceScaling(
scale=1. / 3., mode='fan_in', distribution='uniform')
self._encoder = encoding_network.EncodingNetwork(
observation_spec,
preprocessing_layers=preprocessing_layers,
preprocessing_combiner=preprocessing_combiner,
conv_layer_params=conv_layer_params,
fc_layer_params=fc_layer_params,
dropout_layer_params=dropout_layer_params,
activation_fn=activation_fn,
kernel_initializer=kernel_initializer,
batch_squash=False)
initializer = tf.keras.initializers.RandomUniform(
minval=-0.003, maxval=0.003)
self._action_projection_layer = tf.keras.layers.Dense(
flat_action_spec[0].shape.num_elements(),
activation=tf.keras.activations.tanh,
kernel_initializer=initializer,
name='action')
def call(self, observations, step_type=(), network_state=()):
outer_rank = nest_utils.get_outer_rank(observations, self.input_tensor_spec)
# We use batch_squash here in case the observations have a time sequence
# compoment.
batch_squash = utils.BatchSquash(outer_rank)
observations = tf.nest.map_structure(batch_squash.flatten, observations)
state, network_state = self._encoder(
observations, step_type=step_type, network_state=network_state)
actions = self._action_projection_layer(state)
actions = common_utils.scale_to_spec(actions, self._single_action_spec)
actions = batch_squash.unflatten(actions)
return tf.nest.pack_sequence_as(self._action_spec, [actions]), network_state
Creiamo un RandomPyEnvironment
per generare osservazioni strutturate e convalidare la nostra implementazione.
action_spec = array_spec.BoundedArraySpec((3,), np.float32, minimum=0, maximum=10)
observation_spec = {
'image': array_spec.BoundedArraySpec((16, 16, 3), np.float32, minimum=0,
maximum=255),
'vector': array_spec.BoundedArraySpec((5,), np.float32, minimum=-100,
maximum=100)}
random_env = random_py_environment.RandomPyEnvironment(observation_spec, action_spec=action_spec)
# Convert the environment to a TFEnv to generate tensors.
tf_env = tf_py_environment.TFPyEnvironment(random_env)
Poiché abbiamo definito le osservazioni come un dettato, abbiamo bisogno di creare livelli di pre-elaborazione per gestirli.
preprocessing_layers = {
'image': tf.keras.models.Sequential([tf.keras.layers.Conv2D(8, 4),
tf.keras.layers.Flatten()]),
'vector': tf.keras.layers.Dense(5)
}
preprocessing_combiner = tf.keras.layers.Concatenate(axis=-1)
actor = ActorNetwork(tf_env.observation_spec(),
tf_env.action_spec(),
preprocessing_layers=preprocessing_layers,
preprocessing_combiner=preprocessing_combiner)
Ora che abbiamo la rete di attori, possiamo elaborare le osservazioni dall'ambiente.
time_step = tf_env.reset()
actor(time_step.observation, time_step.step_type)
(<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[4.5753636, 4.946792 , 4.853481 ]], dtype=float32)>, ())
Questa stessa strategia può essere utilizzata per personalizzare qualsiasi delle principali reti utilizzate dagli agenti. Puoi definire qualsiasi pre-elaborazione e connetterla al resto della rete. Quando definisci la tua personalizzazione, assicurati che le definizioni del livello di output della rete corrispondano.