Copyright 2021 Autorzy TF-Agents.
Zobacz na TensorFlow.org | Uruchom w Google Colab | Wyświetl źródło na GitHub | Pobierz notatnik |
Wstęp
W terminologii uczenia się przez wzmacnianie, zasady odwzorowują obserwację ze środowiska na działanie lub podział na działania. W TF-pełnomocników, obserwacje z otoczenia są zawarte w nazwie krotki TimeStep('step_type', 'discount', 'reward', 'observation')
, a polityka map timesteps do działań lub dystrybucji ponad działań. Większość polis używać timestep.observation
niektóre zasady korzystania timestep.step_type
(np aby przywrócić stan na początku epizodu w polityce stanowych), ale timestep.discount
i timestep.reward
są zazwyczaj ignorowane.
Zasady są powiązane z innymi komponentami TF-Agents w następujący sposób. Większość zasad ma sieć neuronową do obliczania akcji i/lub dystrybucji w ramach akcji z TimeSteps. Agenci mogą zawierać jedną lub więcej zasad do różnych celów, np. główną zasadę, która jest szkolona do wdrażania, oraz zaszumioną zasadę gromadzenia danych. Polityki mogą być zapisywane/przywracane i mogą być używane niezależnie od agenta do zbierania danych, oceny itp.
Niektóre polityki są łatwiejsze do napisania w Tensorflow (np. te z siecią neuronową), podczas gdy inne są łatwiejsze do napisania w Pythonie (np. po skrypcie działań). Tak więc w agentach TF dopuszczamy zarówno polityki Pythona, jak i Tensorflow. Co więcej, polityki napisane w TensorFlow mogą wymagać użycia w środowisku Python lub odwrotnie, np. polityka TensorFlow jest używana do szkolenia, ale później jest wdrażana w środowisku produkcyjnym Python. Aby to ułatwić, udostępniamy wrappery do konwersji między politykami Pythona i TensorFlow.
Inną ciekawą klasą polityk są wrappery polityk, które modyfikują daną politykę w określony sposób, np. dodają określony rodzaj szumu, tworzą zachłanną lub epsilon-greedy wersję polityki stochastycznej, losowo mieszają wiele polityk itp.
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 tensorflow_probability as tfp
import numpy as np
from tf_agents.specs import array_spec
from tf_agents.specs import tensor_spec
from tf_agents.networks import network
from tf_agents.policies import py_policy
from tf_agents.policies import random_py_policy
from tf_agents.policies import scripted_py_policy
from tf_agents.policies import tf_policy
from tf_agents.policies import random_tf_policy
from tf_agents.policies import actor_policy
from tf_agents.policies import q_policy
from tf_agents.policies import greedy_policy
from tf_agents.trajectories import time_step as ts
Zasady Pythona
Interfejs dla polityki Pythona jest zdefiniowany w policies/py_policy.PyPolicy
. Główne metody to:
class Base(object):
@abc.abstractmethod
def __init__(self, time_step_spec, action_spec, policy_state_spec=()):
self._time_step_spec = time_step_spec
self._action_spec = action_spec
self._policy_state_spec = policy_state_spec
@abc.abstractmethod
def reset(self, policy_state=()):
# return initial_policy_state.
pass
@abc.abstractmethod
def action(self, time_step, policy_state=()):
# return a PolicyStep(action, state, info) named tuple.
pass
@abc.abstractmethod
def distribution(self, time_step, policy_state=()):
# Not implemented in python, only for TF policies.
pass
@abc.abstractmethod
def update(self, policy):
# update self to be similar to the input `policy`.
pass
@property
def time_step_spec(self):
return self._time_step_spec
@property
def action_spec(self):
return self._action_spec
@property
def policy_state_spec(self):
return self._policy_state_spec
Najważniejszą metodą jest action(time_step)
, który mapuje time_step
zawierający obserwacje z otoczenia do PolicyStep nazwana krotki zawierającej następujące atrybuty:
-
action
: Działanie, które ma być stosowane do środowiska. -
state
: stan polityki (np państwowej RNN) być podawany do kolejnego wezwania do działania. -
info
: Opcjonalne informacje poboczne, takie jak prawdopodobieństw dziennika działanie.
time_step_spec
i action_spec
są specyfikacje dla kroku czasowego wejściowego i wyjściowego działania. Zasady mają również reset
funkcji, która jest zazwyczaj używany do resetowania stanu w polityce stanowych. update(new_policy)
Funkcja aktualizuje self
w kierunku new_policy
.
Przyjrzyjmy się teraz kilku przykładom zasad Pythona.
Przykład 1: Losowa polityka Pythona
Prostym przykładem PyPolicy
jest RandomPyPolicy
który generuje losowe działania dyskretnej / ciągłego danego action_spec. Wejście time_step
jest ignorowany.
action_spec = array_spec.BoundedArraySpec((2,), np.int32, -10, 10)
my_random_py_policy = random_py_policy.RandomPyPolicy(time_step_spec=None,
action_spec=action_spec)
time_step = None
action_step = my_random_py_policy.action(time_step)
print(action_step)
action_step = my_random_py_policy.action(time_step)
print(action_step)
PolicyStep(action=array([10, -4], dtype=int32), state=(), info=()) PolicyStep(action=array([7, 6], dtype=int32), state=(), info=())
Przykład 2: Skryptowana polityka Pythona
A oskryptowane odgrywa polityka kopii skryptu działań przedstawionych w postaci listy (num_repeats, action)
krotek. Za każdym razem, gdy action
wywoływana jest funkcja, zwraca następną akcję z listy aż do określonej liczby powtórzeń jest zrobione, a następnie przechodzi do następnej akcji na liście. reset
sposób można nazwać zacząć realizować od początku listy.
action_spec = array_spec.BoundedArraySpec((2,), np.int32, -10, 10)
action_script = [(1, np.array([5, 2], dtype=np.int32)),
(0, np.array([0, 0], dtype=np.int32)), # Setting `num_repeats` to 0 will skip this action.
(2, np.array([1, 2], dtype=np.int32)),
(1, np.array([3, 4], dtype=np.int32))]
my_scripted_py_policy = scripted_py_policy.ScriptedPyPolicy(
time_step_spec=None, action_spec=action_spec, action_script=action_script)
policy_state = my_scripted_py_policy.get_initial_state()
time_step = None
print('Executing scripted policy...')
action_step = my_scripted_py_policy.action(time_step, policy_state)
print(action_step)
action_step= my_scripted_py_policy.action(time_step, action_step.state)
print(action_step)
action_step = my_scripted_py_policy.action(time_step, action_step.state)
print(action_step)
print('Resetting my_scripted_py_policy...')
policy_state = my_scripted_py_policy.get_initial_state()
action_step = my_scripted_py_policy.action(time_step, policy_state)
print(action_step)
Executing scripted policy... PolicyStep(action=array([5, 2], dtype=int32), state=[0, 1], info=()) PolicyStep(action=array([1, 2], dtype=int32), state=[2, 1], info=()) PolicyStep(action=array([1, 2], dtype=int32), state=[2, 2], info=()) Resetting my_scripted_py_policy... PolicyStep(action=array([5, 2], dtype=int32), state=[0, 1], info=())
Zasady TensorFlow
Zasady TensorFlow są zgodne z tym samym interfejsem, co zasady Pythona. Spójrzmy na kilka przykładów.
Przykład 1: Losowa polityka TF
RandomTFPolicy mogą być wykorzystywane do generowania przypadkowych działania zgodnie z danym dyskretnym / ciągłego action_spec
. Wejście time_step
jest ignorowany.
action_spec = tensor_spec.BoundedTensorSpec(
(2,), tf.float32, minimum=-1, maximum=3)
input_tensor_spec = tensor_spec.TensorSpec((2,), tf.float32)
time_step_spec = ts.time_step_spec(input_tensor_spec)
my_random_tf_policy = random_tf_policy.RandomTFPolicy(
action_spec=action_spec, time_step_spec=time_step_spec)
observation = tf.ones(time_step_spec.observation.shape)
time_step = ts.restart(observation)
action_step = my_random_tf_policy.action(time_step)
print('Action:')
print(action_step.action)
Action: tf.Tensor([-0.9448042 1.9039011], shape=(2,), dtype=float32)
Przykład 2: Polityka aktora
Polityka aktor mogą być tworzone przy użyciu sieci, która mapuje time_steps
działań lub sieć, która mapuje time_steps
podziału ponad działań.
Korzystanie z sieci akcji
Zdefiniujmy sieć w następujący sposób:
class ActionNet(network.Network):
def __init__(self, input_tensor_spec, output_tensor_spec):
super(ActionNet, self).__init__(
input_tensor_spec=input_tensor_spec,
state_spec=(),
name='ActionNet')
self._output_tensor_spec = output_tensor_spec
self._sub_layers = [
tf.keras.layers.Dense(
action_spec.shape.num_elements(), activation=tf.nn.tanh),
]
def call(self, observations, step_type, network_state):
del step_type
output = tf.cast(observations, dtype=tf.float32)
for layer in self._sub_layers:
output = layer(output)
actions = tf.reshape(output, [-1] + self._output_tensor_spec.shape.as_list())
# Scale and shift actions to the correct range if necessary.
return actions, network_state
W TensorFlow większość warstw sieciowych jest zaprojektowana do operacji wsadowych, więc oczekujemy, że wejściowe time_steps będą grupowane, a dane wyjściowe sieci również będą grupowane. Również sieć jest odpowiedzialna za tworzenie akcji w odpowiednim zakresie podanego action_spec. Jest to zwykle wykonywane przy użyciu na przykład tanh aktywacji dla ostatniej warstwy na działania produkcji w [1, 1], a następnie skalowanie i przerzucenie do prawidłowego zakresu, action_spec pomiarowego (patrz np tf_agents/agents/ddpg/networks.actor_network()
).
Teraz możemy stworzyć politykę aktora za pomocą powyższej sieci.
input_tensor_spec = tensor_spec.TensorSpec((4,), tf.float32)
time_step_spec = ts.time_step_spec(input_tensor_spec)
action_spec = tensor_spec.BoundedTensorSpec((3,),
tf.float32,
minimum=-1,
maximum=1)
action_net = ActionNet(input_tensor_spec, action_spec)
my_actor_policy = actor_policy.ActorPolicy(
time_step_spec=time_step_spec,
action_spec=action_spec,
actor_network=action_net)
Możemy zastosować go do dowolnej partii time_steps następujących po time_step_spec:
batch_size = 2
observations = tf.ones([2] + time_step_spec.observation.shape.as_list())
time_step = ts.restart(observations, batch_size)
action_step = my_actor_policy.action(time_step)
print('Action:')
print(action_step.action)
distribution_step = my_actor_policy.distribution(time_step)
print('Action distribution:')
print(distribution_step.action)
Action: tf.Tensor( [[0.9318627 0.7770741 0.8645338] [0.9318627 0.7770741 0.8645338]], shape=(2, 3), dtype=float32) Action distribution: tfp.distributions.Deterministic("Deterministic", batch_shape=[2, 3], event_shape=[], dtype=float32)
W powyższym przykładzie stworzyliśmy politykę przy użyciu sieci akcji, która generuje tensor akcji. W tym przypadku, policy.distribution(time_step)
jest deterministyczny (delta) rozkład wokół wyjścia policy.action(time_step)
. Jednym ze sposobów stworzenia strategii stochastycznej jest opakowanie strategii aktora w opakowanie polityki, które dodaje szum do działań. Innym sposobem jest utworzenie zasad aktora przy użyciu sieci dystrybucji akcji zamiast sieci akcji, jak pokazano poniżej.
Korzystanie z sieci dystrybucji akcji
class ActionDistributionNet(ActionNet):
def call(self, observations, step_type, network_state):
action_means, network_state = super(ActionDistributionNet, self).call(
observations, step_type, network_state)
action_std = tf.ones_like(action_means)
return tfp.distributions.MultivariateNormalDiag(action_means, action_std), network_state
action_distribution_net = ActionDistributionNet(input_tensor_spec, action_spec)
my_actor_policy = actor_policy.ActorPolicy(
time_step_spec=time_step_spec,
action_spec=action_spec,
actor_network=action_distribution_net)
action_step = my_actor_policy.action(time_step)
print('Action:')
print(action_step.action)
distribution_step = my_actor_policy.distribution(time_step)
print('Action distribution:')
print(distribution_step.action)
Action: tf.Tensor( [[ 0.96731853 1. 1. ] [ 0.94488937 -0.29294527 1. ]], shape=(2, 3), dtype=float32) Action distribution: tfp.distributions.MultivariateNormalDiag("ActionNet_MultivariateNormalDiag", batch_shape=[2], event_shape=[3], dtype=float32)
Zauważ, że w powyższym przykładzie akcje są przycinane do zakresu podanej specyfikacji akcji [-1, 1]. Dzieje się tak, ponieważ argument konstruktora ActorPolicy clip=True domyślnie. Ustawienie tego na false zwróci nieobcięte akcje wytwarzane przez sieć.
Stochastyczne zasady może być przekształcany do deterministycznych zasady przy użyciu, na przykład, owijki GreedyPolicy które wybiera stochastic_policy.distribution().mode()
, jak i jego działania, deterministyczną rozkład / delta wokół tego chciwego działania jako jego distribution()
.
Przykład 3: Polityka Q
Zasady AQ są używane w agentach takich jak DQN i opierają się na sieci Q, która przewiduje wartość Q dla każdego działania dyskretnego. Dla danego kroku czasowego rozkład akcji w zasadach Q jest rozkładem kategorycznym utworzonym przy użyciu wartości q jako logit.
input_tensor_spec = tensor_spec.TensorSpec((4,), tf.float32)
time_step_spec = ts.time_step_spec(input_tensor_spec)
action_spec = tensor_spec.BoundedTensorSpec((),
tf.int32,
minimum=0,
maximum=2)
num_actions = action_spec.maximum - action_spec.minimum + 1
class QNetwork(network.Network):
def __init__(self, input_tensor_spec, action_spec, num_actions=num_actions, name=None):
super(QNetwork, self).__init__(
input_tensor_spec=input_tensor_spec,
state_spec=(),
name=name)
self._sub_layers = [
tf.keras.layers.Dense(num_actions),
]
def call(self, inputs, step_type=None, network_state=()):
del step_type
inputs = tf.cast(inputs, tf.float32)
for layer in self._sub_layers:
inputs = layer(inputs)
return inputs, network_state
batch_size = 2
observation = tf.ones([batch_size] + time_step_spec.observation.shape.as_list())
time_steps = ts.restart(observation, batch_size=batch_size)
my_q_network = QNetwork(
input_tensor_spec=input_tensor_spec,
action_spec=action_spec)
my_q_policy = q_policy.QPolicy(
time_step_spec, action_spec, q_network=my_q_network)
action_step = my_q_policy.action(time_steps)
distribution_step = my_q_policy.distribution(time_steps)
print('Action:')
print(action_step.action)
print('Action distribution:')
print(distribution_step.action)
Action: tf.Tensor([2 2], shape=(2,), dtype=int32) Action distribution: tfp.distributions.Categorical("Categorical", batch_shape=[2], event_shape=[], dtype=int32)
Opakowania polis
Opakowania polityk można użyć do pakowania i modyfikowania danej polityki, np. dodawania szumu. Opakowania zasad są podklasą zasad (Python/TensorFlow) i dlatego mogą być używane tak samo jak inne zasady.
Przykład: Polityka chciwości
Chciwy Owijka może być stosowany w stosunku do dowolnych zasady TensorFlow implementującej distribution()
. GreedyPolicy.action()
powróci wrapped_policy.distribution().mode()
i GreedyPolicy.distribution()
jest deterministyczny rozkład / delta około GreedyPolicy.action()
:
my_greedy_policy = greedy_policy.GreedyPolicy(my_q_policy)
action_step = my_greedy_policy.action(time_steps)
print('Action:')
print(action_step.action)
distribution_step = my_greedy_policy.distribution(time_steps)
print('Action distribution:')
print(distribution_step.action)
Action: tf.Tensor([1 1], shape=(2,), dtype=int32) Action distribution: tfp.distributions.DeterministicWithLogProb("Deterministic", batch_shape=[2], event_shape=[], dtype=int32)