版权所有 2023 TF-Agents 作者。
在 TensorFlow.org 上查看 | 在 Google Colab 中运行 | 在 GitHub 上查看源代码 | 下载笔记本 |
简介
在这个 Colab 中,我们将介绍如何为您的代理定义自定义网络。网络帮助我们定义代理训练的模型。在 TF-Agents 中,您会发现几种不同类型的网络,这些网络在代理之间非常有用
主要网络
- QNetwork:用于具有离散动作的环境的 Q 学习,该网络将观察结果映射到每个可能动作的值估计。
- CriticNetworks:在文献中也称为
ValueNetworks
,学习估计价值函数的某种版本,该函数将某个状态映射到策略预期回报的估计值。这些网络估计代理当前所处的状态有多好。 - ActorNetworks:学习从观察结果到动作的映射。这些网络通常由我们的策略用来生成动作。
- ActorDistributionNetworks:类似于
ActorNetworks
,但这些网络生成一个分布,然后策略可以从中采样以生成动作。
辅助网络
- EncodingNetwork:允许用户轻松定义要应用于网络输入的预处理层映射。
- DynamicUnrollLayer:在它应用于时间序列时,会在情节边界自动重置网络的状态。
- ProjectionNetwork:像
CategoricalProjectionNetwork
或NormalProjectionNetwork
这样的网络接受输入并生成生成分类或正态分布所需的参数。
TF-Agents 中的所有示例都附带预配置的网络。但是,这些网络没有设置为处理复杂的观察结果。
如果您有一个环境,它公开了一个以上的观察结果/动作,并且您需要自定义网络,那么本教程适合您!
设置
如果您尚未安装 tf-agents,请运行
pip install tf-agents
pip install tf-keras
import os
# Keep using keras-2 (tf-keras) rather than keras-3 (keras).
os.environ['TF_USE_LEGACY_KERAS'] = '1'
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-Agents 中,我们从 Keras 网络 中继承。有了它,我们可以
- 简化创建目标网络时所需的复制操作。
- 在调用
network.variables()
时执行自动变量创建。 - 根据网络 input_specs 验证输入。
EncodingNetwork
如上所述,EncodingNetwork
允许我们轻松定义要应用于网络输入的预处理层映射,以生成某种编码。
EncodingNetwork 由以下大部分可选层组成
- 预处理层
- 预处理组合器
- Conv2D
- Flatten
- Dense
编码网络的特殊之处在于应用了输入预处理。输入预处理可以通过 preprocessing_layers
和 preprocessing_combiner
层实现。这些层都可以指定为嵌套结构。如果 preprocessing_layers
嵌套比 input_tensor_spec
浅,那么这些层将获取子嵌套。例如,如果
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)
/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tf_agents/specs/array_spec.py:352: RuntimeWarning: invalid value encountered in cast self._minimum[self._minimum == -np.inf] = low /tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tf_agents/specs/array_spec.py:353: RuntimeWarning: invalid value encountered in cast self._minimum[self._minimum == np.inf] = high /tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tf_agents/specs/array_spec.py:355: RuntimeWarning: invalid value encountered in cast self._maximum[self._maximum == -np.inf] = low /tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tf_agents/specs/array_spec.py:356: RuntimeWarning: invalid value encountered in cast self._maximum[self._maximum == np.inf] = high
由于我们已将观察结果定义为字典,因此我们需要创建预处理层来处理这些观察结果。
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)
现在我们有了 Actor 网络,我们可以处理来自环境的观察结果。
time_step = tf_env.reset()
actor(time_step.observation, time_step.step_type)
/tmpfs/src/tf_docs_env/lib/python3.9/site-packages/tf_keras/src/initializers/initializers.py:121: UserWarning: The initializer VarianceScaling is unseeded and being called multiple times, which will return identical values each time (even if the initializer is unseeded). Please update your code to provide a seed to the initializer, or avoid using the same initializer instance more than once. warnings.warn( (<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[5.8357787, 4.3249702, 3.6428978]], dtype=float32)>, ())
相同的策略可用于自定义代理使用的任何主要网络。您可以定义任何预处理,并将其连接到网络的其余部分。在定义自己的自定义网络时,请确保网络的输出层定义匹配。