حق چاپ 2021 نویسندگان TF-Agents.
مشاهده در TensorFlow.org | در Google Colab اجرا شود | مشاهده منبع در GitHub | دانلود دفترچه یادداشت |
معرفی
در اصطلاحات یادگیری تقویتی، خط مشی ها یک مشاهده از محیط را به یک عمل یا توزیع بر روی کنش ها ترسیم می کنند. در TF-نمایندگی ها، مشاهدات از محیط در یک تاپل به نام موجود TimeStep('step_type', 'discount', 'reward', 'observation')
، و سیاست های نقشه timesteps به اقدامات و یا توزیع بیش از اقدامات. اکثر سیاست های استفاده از timestep.observation
، برخی از سیاست های استفاده از timestep.step_type
(به عنوان مثال برای تنظیم مجدد دولت در آغاز یک قسمت که در سیاست های stateful به)، اما timestep.discount
و timestep.reward
معمولا نادیده گرفته میشود.
خط مشی ها به روش زیر با سایر اجزای موجود در TF-Agents مرتبط می شوند. بیشتر خطمشیها دارای یک شبکه عصبی برای محاسبه اقدامات و/یا توزیعها بر روی اقدامات از TimeSteps هستند. عامل ها می توانند شامل یک یا چند خط مشی برای اهداف مختلف باشند، به عنوان مثال یک خط مشی اصلی که برای استقرار آموزش داده می شود و یک خط مشی پر سر و صدا برای جمع آوری داده ها. خطمشیها را میتوان ذخیره/بازیابی کرد و بهطور مستقل از عامل برای جمعآوری دادهها، ارزیابی و غیره استفاده کرد.
نوشتن برخی از خط مشی ها در تنسورفلو آسان تر است (مثلاً آنهایی که دارای شبکه عصبی هستند)، در حالی که نوشتن برخی دیگر در پایتون آسان تر است (مثلاً دنبال کردن یک اسکریپت از اقدامات). بنابراین در عامل های TF، ما هر دو خط مشی Python و Tensorflow را مجاز می کنیم. علاوه بر این، سیاستهای نوشته شده در TensorFlow ممکن است در یک محیط پایتون استفاده شوند، یا برعکس، به عنوان مثال، یک خطمشی TensorFlow برای آموزش استفاده میشود اما بعداً در یک محیط پایتون تولیدی مستقر میشود. برای آسانتر کردن این کار، ما پوششهایی برای تبدیل بین خطمشیهای پایتون و تنسورفلو ارائه میکنیم.
یکی دیگر از دستهبندیهای جالب سیاستها، پوششهای خطمشی هستند که یک خطمشی معین را به روشی خاص تغییر میدهند، مثلاً نوع خاصی از نویز را اضافه میکنند، نسخهای حریصانه یا اپسیلونی از یک خطمشی تصادفی ایجاد میکنند، بهطور تصادفی چندین خطمشی را مخلوط میکنند و غیره.
برپایی
اگر هنوز tf-agents را نصب نکرده اید، اجرا کنید:
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
سیاست های پایتون
رابط کاربری را برای سیاست های پایتون در تعریف policies/py_policy.PyPolicy
. روش های اصلی عبارتند از:
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
بیشترین روش مهم است action(time_step)
است که نقشه یک time_step
حاوی یک مشاهده از محیط زیست برای یک تاپل PolicyStep نام حاوی ویژگی های زیر:
-
action
: عملی به به محیط زیست استفاده شود. -
state
: دولت از سیاست (به عنوان مثال RNN دولت) به تماس بعدی به عمل تغذیه می شود. -
info
: اطلاعات جانبی اختیاری مانند احتمال اقدام ورود به سیستم.
time_step_spec
و action_spec
مشخصات ورودی گام زمان و عمل خروجی می باشد. سیاست همچنین یک reset
تابع است که به طور معمول برای بازنشانی دولت در سیاست های stateful به استفاده می شود. update(new_policy)
تابع به روز رسانی self
به سمت new_policy
.
حال، اجازه دهید به چند نمونه از سیاست های پایتون نگاهی بیندازیم.
مثال 1: خط مشی پایتون تصادفی
یک مثال ساده از یک PyPolicy
است RandomPyPolicy
که تولید اقدامات تصادفی برای گسسته / مستمر action_spec داده شده است. ورودی time_step
نادیده گرفته است.
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=())
مثال 2: خط مشی پایتون اسکریپت شده
نمایشنامه سیاست اسکریپت یک اسکریپت از اقدامات به عنوان نماینده یک لیست از (num_repeats, action)
چندتایی ها. هر بار که action
تابع نامیده می شود، آن اقدام بعدی را از لیست باز می گردد تا زمانی که تعداد مشخصی از تکرار انجام شده است، و سپس به اقدام بعدی در لیست حرکت می کند. reset
روش می توان به نام برای شروع اجرای از آغاز این فهرست است.
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=())
سیاست های TensorFlow
خط مشی های TensorFlow از رابطی مشابه با سیاست های پایتون پیروی می کنند. اجازه دهید به چند نمونه نگاه کنیم.
مثال 1: خط مشی TF تصادفی
RandomTFPolicy می توان مورد استفاده برای تولید اقدامات تصادفی با توجه به گسسته / به طور مستمر پرداخت action_spec
. ورودی time_step
نادیده گرفته است.
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)
مثال 2: سیاست بازیگر
یک سیاست بازیگر می توان با استفاده از یک شبکه است که نقشه ایجاد time_steps
به اقدامات و یا یک شبکه است که نقشه time_steps
به توزیع بیش از اقدامات.
استفاده از شبکه عمل
اجازه دهید شبکه را به صورت زیر تعریف کنیم:
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
در TensorFlow اکثر لایههای شبکه برای عملیات دستهای طراحی شدهاند، بنابراین انتظار داریم که time_steps ورودی دستهبندی شود و خروجی شبکه نیز دستهبندی شود. همچنین شبکه مسئول تولید اقدامات در محدوده صحیح action_spec است. طبق قرارداد انجام با استفاده از به عنوان مثال یک tanh فعال سازی برای لایه نهایی به اقدامات تولید در -1، 1] و سپس پوسته پوسته شدن و تغییر این به محدوده درست به عنوان action_spec ورودی (به عنوان مثال دیدن tf_agents/agents/ddpg/networks.actor_network()
).
اکنون میتوانیم با استفاده از شبکه بالا یک سیاست بازیگر ایجاد کنیم.
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)
ما می توانیم آن را برای هر دسته ای از time_steps که از 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)
در مثال بالا، ما خط مشی را با استفاده از یک شبکه اکشن ایجاد کردیم که یک تانسور عمل تولید می کند. در این مورد، policy.distribution(time_step)
قطعی (دلتا) توزیع در سراسر خروجی است policy.action(time_step)
. یکی از راههای تولید یک خطمشی تصادفی این است که سیاست بازیگر را در یک بستهبندی خطمشی بپیچید که نویز را به کنشها اضافه کند. راه دیگر ایجاد خط مشی کنشگر با استفاده از شبکه توزیع کنش به جای شبکه عمل است که در زیر نشان داده شده است.
استفاده از شبکه توزیع کنش
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)
توجه داشته باشید که در بالا، اکشنها به محدوده مشخصات عمل داده شده [-1، 1] بریده میشوند. دلیل این امر این است که به طور پیش فرض یک آرگومان سازنده ActorPolicy clip=True است. با تنظیم این مقدار به false، اقدامات بریده نشده تولید شده توسط شبکه برمی گردد.
سیاست های تصادفی را می توان به سیاست های قطعی با استفاده از، برای مثال، یک لفاف بسته بندی GreedyPolicy که را تبدیل stochastic_policy.distribution().mode()
به عنوان عمل خود را، و یک توزیع / دلتا قطعی در اطراف این عمل حریص به عنوان آن distribution()
.
مثال 3: خط مشی Q
خط مشی AQ در عواملی مانند DQN استفاده می شود و مبتنی بر یک شبکه Q است که مقدار Q را برای هر اقدام گسسته پیش بینی می کند. برای یک مرحله زمانی معین، توزیع کنش در سیاست Q یک توزیع طبقه بندی شده است که با استفاده از مقادیر q به عنوان 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)
لفاف های سیاست
برای بسته بندی و اصلاح یک خط مشی معین، به عنوان مثال اضافه کردن نویز، می توان از یک پوشش سیاست استفاده کرد. پوششهای سیاست یک زیر کلاس از Policy (Python/TensorFlow) هستند و بنابراین میتوانند مانند هر خطمشی دیگری مورد استفاده قرار گیرند.
مثال: سیاست حریصانه
لفاف حریص می توان برای قرار دادن هر سیاست TensorFlow است که پیاده سازی distribution()
. GreedyPolicy.action()
باز خواهد گشت wrapped_policy.distribution().mode()
و GreedyPolicy.distribution()
یک توزیع / دلتا قطعی در اطراف است 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)