Copyright 2021 The TF-Agents Authors.
TensorFlow.org에서 보기 | Google Colab에서 실행하기 | GitHub에서 소스 보기 | 노트북 다운로드하기 |
소개
이 colab에서는 에이전트에 대한 사용자 정의 네트워크를 정의하는 방법을 다룹니다. 네트워크는 에이전트를 통해 훈련되는 모델을 정의하는 데 도움이 됩니다. TF-Agents에는 에이전트에 유용한 여러 가지 유형의 네트워크가 있습니다.
주요 네트워크
- QNetwork: 불연속 행동이 있는 환경에 대한 Qlearning에서 사용되는 이 네트워크는 관찰 값을 가능한 각 행동에 대한 추정 값에 매핑합니다.
- CriticNetworks: 문헌에서
ValueNetworks
라고도 하며 일부 상태를 예상되는 정책 반환의 추정에 매핑하는 일부 Value 함수 버전을 추정하는 방법을 학습합니다. 이 네트워크는 에이전트의 현재 상태가 얼마나 좋은지 추정합니다. - ActorNetworks: 관찰 값에서 행동으로의 매핑을 학습합니다. 이러한 네트워크는 일반적으로 정책에서 행동을 생성하는 데 사용됩니다.
- 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
tf.compat.v1.enable_v2_behavior()
네트워크 정의하기
네트워크 API
TF-Agents에서는 Keras Networks를 하위 클래스화합니다. 그러면 다음을 수행할 수 있습니다.
- 대상 네트워크를 만들 때 필요한 복사 작업을 단순화합니다.
network.variables()
를 호출할 때 자동 변수 생성을 수행합니다.- 네트워크 input_spec을 기반으로 입력을 검증합니다.
EncodingNetwork는 대부분 선택적인 다음과 같은 레이어로 구성됩니다.
네트워크 인코딩의 특별한 점은 입력 전처리가 적용된다는 것입니다. 입력 전처리는 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](obsrevations[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)
이제 actor 네트워크가 생겼으므로 환경에서 관찰 값을 처리할 수 있습니다.
time_step = tf_env.reset()
actor(time_step.observation, time_step.step_type)
(<tf.Tensor: shape=(1, 3), dtype=float32, numpy=array([[4.866429, 5.182047, 5.05543 ]], dtype=float32)>, ())
이 같은 전략을 사용하여 에이전트가 사용하는 기본 네트워크를 사용자 정의 할 수 있습니다. 전처리를 정의하고 나머지 네트워크에 연결할 수 있습니다. 사용자 정의를 정의 할 때 네트워크의 출력 계층 정의가 일치하는지 확인하십시오.