Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

reti

Visualizza su TensorFlow.org Esegui in Google Colab Visualizza sorgente su GitHub Scarica notebook

introduzione

In questa colonna vedremo come definire reti personalizzate per i tuoi agenti. Le reti ci aiutano a definire il modello addestrato dagli agenti. In TF-Agents troverai diversi tipi di reti utili tra gli agenti:

Reti principali

  • QNetwork : utilizzata in Qlearning per ambienti con azioni discrete, questa rete mappa un'osservazione per valutare le stime per ogni possibile azione.
  • CriticNetworks : Chiamato anche ValueNetworks in letteratura, impara a stimare alcune versioni di una funzione Value mappando alcuni stati in una stima per il rendimento atteso di una politica. Queste reti stimano lo stato in cui si trova attualmente l'agente.
  • ActorNetworks : impara una mappatura dalle osservazioni alle azioni. Queste reti vengono solitamente utilizzate dalle nostre politiche per generare azioni.
  • ActorDistributionNetworks : simili a ActorNetworks ma generano una distribuzione che una politica può quindi campionare per generare azioni.

Reti di supporto

  • EncodingNetwork : consente agli utenti di definire facilmente una mappatura dei livelli di pre-elaborazione da applicare all'input di una rete.
  • DynamicUnrollLayer : ripristina automaticamente lo stato della rete sui limiti degli episodi quando viene applicato su una sequenza temporale.
  • ProjectionNetwork : reti come CategoricalProjectionNetwork o NormalProjectionNetwork prendono input e generano i parametri richiesti per generare distribuzioni categoriali o normali.

Tutti gli esempi in TF-Agent vengono 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 è per te!

Impostare

Se non hai ancora installato tf-agent, esegui:

pip install -q 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

tf.compat.v1.enable_v2_behavior()

Definizione di reti

API di rete

In TF-Agents facciamo una sottoclasse di Keras Networks . Con esso possiamo:

  • Semplifica le operazioni di copia richieste durante la creazione di reti di destinazione.
  • Esegue la creazione automatica delle variabili quando si chiama network.variables() .
  • Convalida gli input in base a input_specs di rete.

EncodingNetwork

Come accennato in precedenza, EncodingNetwork ci consente di definire facilmente una mappatura dei livelli di pre-elaborazione da applicare all'input di una rete per generare una codifica.

EncodingNetwork è composto dai seguenti livelli per lo più opzionali:

  • Pre-elaborazione dei livelli
  • Combinatore di pre-elaborazione
  • Conv2D
  • Appiattire
  • Denso

La particolarità della codifica delle reti è che viene applicata la preelaborazione degli input. La preelaborazione dell'input è possibile tramite i livelli preprocessing_layers e preprocessing_combiner . Ciascuno di questi può essere specificato come una struttura nidificata. Se il preprocessing_layers nest è meno profondo di input_tensor_spec , i layer riceveranno i subnest. Ad esempio, se:

input_tensor_spec = ([TensorSpec(3)] * 2, [TensorSpec(3)] * 5)
preprocessing_layers = (Layer1(), Layer2())

quindi la preelaborazione chiamerà:

preprocessed = [preprocessing_layers[0](observations[0]),
                preprocessing_layers[1](obsrevations[1])]

Tuttavia, se

preprocessing_layers = ([Layer1() for _ in range(2)],
                        [Layer2() for _ in range(5)])

quindi la preelaborazione chiamerà:

preprocessed = [
  layer(obs) for layer, obs in zip(flatten(preprocessing_layers),
                                    flatten(observations))
]

Reti personalizzate

Per creare le tue reti dovrai solo sovrascrivere __init__ e call metodi. Creiamo una rete personalizzata usando ciò che abbiamo imparato su EncodingNetworks per creare un ActorNetwork che prende 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 dict, dobbiamo creare livelli di preelaborazione per gestirle.

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([[7.026863 , 4.5458393, 4.7681847]], dtype=float32)>,
 ())

Questa stessa strategia può essere utilizzata per personalizzare una qualsiasi delle reti principali utilizzate dagli agenti. È possibile definire qualsiasi preelaborazione e collegarla al resto della rete. Mentre definisci la tua personalizzazione, assicurati che le definizioni del livello di output della rete corrispondano.