Авторские права 2021 Авторы TF-Agents.
Посмотреть на TensorFlow.org | Запускаем в Google Colab | Посмотреть исходный код на GitHub | Скачать блокнот |
Введение
В этой статье мы расскажем, как определять собственные сети для ваших агентов. Сети помогают нам определить модель, которую обучают агенты. В TF-Agents вы найдете несколько различных типов сетей, которые могут использоваться агентами:
Основные сети
- QNetwork: Используется в Qlearning для сред с дискретными действиями, эта сеть сопоставляет наблюдения для оценки стоимости для каждого возможного действия.
- CriticNetworks: Также упоминается как
ValueNetworks
в литературе, учится оценивать какую - то версию функции Value отображающей некоторое состояние в оценке ожидаемой доходности политики. Эти сети оценивают, насколько хорошо в настоящее время находится агент. - ActorNetworks: Learn отображение от наблюдений к действиям. Эти сети обычно используются нашими политиками для создания действий.
- ActorDistributionNetworks: Аналогичен
ActorNetworks
но этот генерировать распределение, политика может затем образец для создания действия.
Вспомогательные сети
- EncodingNetwork: Позволяет пользователям легко определить отображение предварительно обработки слоев , чтобы применить для ввода сети.
- DynamicUnrollLayer: Автоматически сбрасывает состояние сети на границах эпизода , как она применяется в течение временной последовательности.
- ProjectionNetwork: Сети как
CategoricalProjectionNetwork
илиNormalProjectionNetwork
принимают входные сигналы и генерируют необходимые параметры для создания категорических или нормальных распределений.
Все примеры в TF-Agents поставляются с предварительно настроенными сетями. Однако эти сети не предназначены для обработки сложных наблюдений.
Если у вас есть среда, которая предоставляет более одного наблюдения / действия, и вам нужно настроить свои сети, то это руководство для вас!
Настраивать
Если вы еще не установили tf-agent, запустите:
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
Определение сетей
Сетевой API
В TF-агентов мы подклассы от Keras сетей . С его помощью мы можем:
- Упростите операции копирования, необходимые при создании целевых сетей.
- Выполнить автоматическое создание переменных при вызове
network.variables()
. - Проверять входные данные на основе сетевых input_specs.
EncodingNetwork
Как уже упоминалось выше EncodingNetwork
позволяет легко определить отображение слоев предварительной обработки применять для ввода сети , чтобы сгенерировать кодировку.
EncodingNetwork состоит из следующих в основном необязательных уровней:
- Предварительная обработка слоев
- Объединитель предварительной обработки
- Conv2D
- Сплющивать
- Плотный
Особенностью сетей кодирования является то, что применяется предварительная обработка входных данных. Ввод предварительной обработки можно с помощью preprocessing_layers
и preprocessing_combiner
слоев. Каждый из них может быть определен как вложенная структура. Если preprocessing_layers
гнездо мельче , чем input_tensor_spec
, то слои будут получать subnests. Например, если:
input_tensor_spec = ([TensorSpec(3)] * 2, [TensorSpec(3)] * 5)
preprocessing_layers = (Layer1(), Layer2())
тогда предварительная обработка вызовет:
preprocessed = [preprocessing_layers[0](observations[0]),
preprocessing_layers[1](observations[1])]
Однако если
preprocessing_layers = ([Layer1() for _ in range(2)],
[Layer2() for _ in range(5)])
тогда предварительная обработка вызовет:
preprocessed = [
layer(obs) for layer, obs in zip(flatten(preprocessing_layers),
flatten(observations))
]
Пользовательские сети
Для того, чтобы создавать свои собственные сети , вы будете иметь только переопределить __init__
и call
методов. Давайте создать пользовательскую сеть , используя то , что мы узнали о EncodingNetworks
по созданию ActorNetwork , которая принимает замечания , которые содержат изображения и вектор.
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
Давайте создадим RandomPyEnvironment
для создания структурированных наблюдений и проверки нашей реализации.
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)
Поскольку мы определили наблюдения как диктант, нам нужно создать слои предварительной обработки для их обработки.
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)
Теперь, когда у нас есть сеть акторов, мы можем обрабатывать наблюдения из окружающей среды.
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)>, ())
Эту же стратегию можно использовать для настройки любой из основных сетей, используемых агентами. Вы можете определить любую предварительную обработку и подключить ее к остальной части сети. Когда вы определяете свой собственный заказ, убедитесь, что определения выходного слоя сети совпадают.