Sieci

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Wstęp

W tej kolaboracji omówimy, jak zdefiniować niestandardowe sieci dla agentów. Sieci pomagają nam zdefiniować model, który jest szkolony przez agentów. W TF-Agents znajdziesz kilka różnych typów sieci, które są przydatne dla agentów:

Główne sieci

  • QNetwork: Używany w Qlearning dla środowisk o dyskretnych działań, sieć ta odwzorowuje obserwację do szacunków wartości dla każdego możliwego działania.
  • CriticNetworks: Także dalej ValueNetworks w literaturze, uczy się oszacować jakąś wersję funkcji Wartość mapujesz stanu do oszacowania dla oczekiwanego zwrotu polityki. Sieci te szacują, w jakim stanie znajduje się obecnie agent.
  • ActorNetworks: Dowiedz się mapowanie z uwagi na działania. Te sieci są zwykle używane przez nasze zasady do generowania działań.
  • ActorDistributionNetworks: podobne do ActorNetworks ale te generują rozkład których polityka może następnie próbki do generowania działań.

Sieci pomocnicze

  • EncodingNetwork: Pozwala użytkownikom łatwo zdefiniować odwzorowanie wstępne przetwarzanie warstw zastosować, aby wprowadzić sieci.
  • DynamicUnrollLayer: Automatycznie przywraca stan w sieci na granicach odcinka, ponieważ nakłada się sekwencji czasowej.
  • ProjectionNetwork: Sieci takie jak CategoricalProjectionNetwork lub NormalProjectionNetwork wziąć wejść i generuje wymagane parametry do generowania kategoryczne lub dystrybucje normalne.

Wszystkie przykłady w TF-Agents są dostarczane ze wstępnie skonfigurowanymi sieciami. Jednak sieci te nie są przystosowane do obsługi złożonych obserwacji.

Jeśli masz środowisko, które ujawnia więcej niż jedną obserwację/działanie i potrzebujesz dostosować swoje sieci, ten samouczek jest dla Ciebie!

Ustawiać

Jeśli nie zainstalowałeś jeszcze agentów tf, uruchom:

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

Definiowanie sieci

Sieciowy interfejs API

W TF-pełnomocników my podklasy z Keras Networks . Dzięki niemu możemy:

  • Uprość operacje kopiowania wymagane podczas tworzenia sieci docelowych.
  • Wykonaj automatyczne tworzenie zmiennej Dzwoniąc network.variables() .
  • Sprawdź poprawność danych wejściowych na podstawie danych wejściowych sieci.

KodowanieSieć

Jak wspomniano powyżej EncodingNetwork pozwala nam łatwo zdefiniować odwzorowanie warstw wstępnego przetwarzania zastosować, aby wprowadzić sieci do generowania jakieś kodowanie.

EncodingNetwork składa się z następujących, przeważnie opcjonalnych warstw:

  • Wstępne przetwarzanie warstw
  • Łącznik przetwarzania wstępnego
  • Conv2D
  • Spłaszczyć
  • Gęsty

Szczególną cechą sieci kodujących jest to, że stosowane jest wstępne przetwarzanie danych wejściowych. Przerób wejście jest możliwe poprzez preprocessing_layers i preprocessing_combiner warstwach. Każdy z nich można określić jako strukturę zagnieżdżoną. Jeśli preprocessing_layers gniazdo jest płytsze niż input_tensor_spec , następnie warstwy dostanie subnests. Na przykład, jeśli:

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

wtedy wstępne przetwarzanie wywoła:

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

Jeśli jednak

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

wtedy wstępne przetwarzanie wywoła:

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

Sieci niestandardowe

Aby tworzyć własne sieci będzie trzeba tylko zastąpić __init__ i call metod. Stwórzmy sieć przy użyciu niestandardowego, czego dowiedzieliśmy się o EncodingNetworks do wydzielać ActorNetwork które ma uwag, które zawierają obraz i wektor.

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

Stwórzmy RandomPyEnvironment generowania obserwacje strukturyzowanych i zweryfikować nasze wdrożenia.

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)

Ponieważ zdefiniowaliśmy obserwacje jako nakaz, musimy utworzyć warstwy przetwarzania wstępnego, aby je obsłużyć.

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)

Teraz, gdy mamy sieć aktorów, możemy przetwarzać obserwacje z otoczenia.

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

Tej samej strategii można użyć do dostosowania dowolnej z głównych sieci używanych przez agentów. Możesz zdefiniować dowolne przetwarzanie wstępne i połączyć je z resztą sieci. Podczas definiowania własnego niestandardowego upewnij się, że definicje warstwy wyjściowej sieci są zgodne.