Cette page a été traduite par l'API Cloud Translation.
Switch to English

Réseaux

Voir sur TensorFlow.org Exécuter dans Google Colab Afficher la source sur GitHub Télécharger le cahier

introduction

Dans ce colab, nous verrons comment définir des réseaux personnalisés pour vos agents. Les réseaux nous aident à définir le modèle formé par les agents. Dans TF-Agents, vous trouverez plusieurs types de réseaux qui sont utiles entre les agents:

Réseaux principaux

  • QNetwork : utilisé dans Qlearning pour les environnements avec des actions discrètes, ce réseau mappe une observation à des estimations de valeur pour chaque action possible.
  • CriticNetworks : également appelé ValueNetworks dans la littérature, apprend à estimer une version d'une fonction Value mappant un état dans une estimation du retour attendu d'une politique. Ces réseaux estiment la qualité de l'état actuel de l'agent.
  • ActorNetworks : apprenez une cartographie des observations aux actions. Ces réseaux sont généralement utilisés par nos politiques pour générer des actions.
  • ActorDistributionNetworks : similaire à ActorNetworks mais ceux-ci génèrent une distribution qu'une politique peut ensuite échantillonner pour générer des actions.

Réseaux d'assistance

  • EncodingNetwork : permet aux utilisateurs de définir facilement un mappage des couches de prétraitement à appliquer à l'entrée d'un réseau.
  • DynamicUnrollLayer : réinitialise automatiquement l'état du réseau sur les limites des épisodes lorsqu'il est appliqué sur une séquence temporelle.
  • ProjectionNetwork : des réseaux tels que CategoricalProjectionNetwork ou NormalProjectionNetwork prennent des entrées et génèrent les paramètres requis pour générer des distributions catégoriques ou normales.

Tous les exemples de TF-Agents sont fournis avec des réseaux préconfigurés. Cependant, ces réseaux ne sont pas configurés pour gérer des observations complexes.

Si vous avez un environnement qui expose plus d'une observation / action et que vous avez besoin de personnaliser vos réseaux, ce tutoriel est fait pour vous!

Installer

Si vous n'avez pas encore installé tf-agents, exécutez:

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

Définition de réseaux

API réseau

Dans TF-Agents, nous sous-classes de Keras Networks . Avec lui, nous pouvons:

  • Simplifiez les opérations de copie requises lors de la création de réseaux cibles.
  • Effectuez la création automatique de variables lors de l'appel de network.variables() .
  • Validez les entrées en fonction de input_specs réseau.

EncodingNetwork

Comme mentionné ci-dessus, EncodingNetwork nous permet de définir facilement un mappage de couches de prétraitement à appliquer à l'entrée d'un réseau pour générer un certain codage.

L'EncodingNetwork est composé des couches suivantes pour la plupart facultatives:

  • Prétraitement des couches
  • Combineur de prétraitement
  • Conv2D
  • Aplatir
  • Dense

La particularité du codage des réseaux est que le prétraitement des entrées est appliqué. Le prétraitement d'entrée est possible via les couches preprocessing_layers et preprocessing_combiner . Chacun de ces éléments peut être spécifié comme une structure imbriquée. Si le preprocessing_layers nid est moins profonde que input_tensor_spec , puis les couches auront la subnests. Par exemple, si:

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

puis le prétraitement appellera:

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

Toutefois, si

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

puis le prétraitement appellera:

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

Réseaux personnalisés

Pour créer vos propres réseaux, vous n'aurez qu'à remplacer les méthodes __init__ et call . Créons un réseau personnalisé en utilisant ce que nous avons appris sur EncodingNetworks pour créer un ActorNetwork qui prend des observations contenant une image et un vecteur.

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

Créons un RandomPyEnvironment pour générer des observations structurées et valider notre implémentation.

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)

Puisque nous avons défini les observations comme étant un dict, nous devons créer des couches de prétraitement pour les gérer.

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)

Maintenant que nous avons le réseau d'acteurs, nous pouvons traiter les observations de l'environnement.

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

Cette même stratégie peut être utilisée pour personnaliser l'un des principaux réseaux utilisés par les agents. Vous pouvez définir n'importe quel prétraitement et le connecter au reste du réseau. Lorsque vous définissez votre propre personnalisation, assurez-vous que les définitions de couche de sortie du réseau correspondent.