حقوق الطبع والنشر 2021 The TF-Agents Authors.
عرض على TensorFlow.org | تشغيل في Google Colab | عرض المصدر على جيثب | تحميل دفتر |
مقدمة
في مصطلحات التعلم التعزيزي ، تحدد السياسات ملاحظة من البيئة إلى إجراء أو توزيع على الإجراءات. في وكلاء TF، وترد ملاحظات من البيئة في الصفوف (tuple) اسمه TimeStep('step_type', 'discount', 'reward', 'observation')
، والسياسات الخريطة timesteps إلى الإجراءات أو التوزيعات على الإجراءات. معظم السياسات تستخدم timestep.observation
، بعض السياسات تستخدم timestep.step_type
(على سبيل المثال لإعادة الدولة في بداية حلقة في سياسات جليل)، ولكن timestep.discount
و timestep.reward
يتم تجاهلها عادة.
ترتبط السياسات بالمكونات الأخرى في TF-Agents بالطريقة التالية. تحتوي معظم السياسات على شبكة عصبية لحساب الإجراءات و / أو التوزيعات على الإجراءات من TimeSteps. يمكن أن يحتوي الوكلاء على سياسة واحدة أو أكثر لأغراض مختلفة ، مثل سياسة رئيسية يتم تدريبها للنشر وسياسة صاخبة لجمع البيانات. يمكن حفظ / استعادة السياسات ، ويمكن استخدامها بشكل مستقل للوكيل لجمع البيانات وتقييمها وما إلى ذلك.
بعض السياسات أسهل في الكتابة في Tensorflow (مثل تلك التي تحتوي على شبكة عصبية) ، في حين أن البعض الآخر أسهل في الكتابة في Python (على سبيل المثال اتباع برنامج نصي من الإجراءات). لذلك في وكلاء TF ، نسمح بكل من سياسات Python و Tensorflow. علاوة على ذلك ، قد يتعين استخدام السياسات المكتوبة في TensorFlow في بيئة Python ، أو العكس ، على سبيل المثال ، يتم استخدام سياسة TensorFlow للتدريب ولكن يتم نشرها لاحقًا في بيئة إنتاج Python. لتسهيل ذلك ، نقدم أغلفة للتحويل بين سياسات Python و TensorFlow.
فئة أخرى مثيرة للاهتمام من السياسات هي أغلفة السياسات ، والتي تعدل سياسة معينة بطريقة معينة ، على سبيل المثال إضافة نوع معين من الضجيج ، أو إنشاء نسخة جشعة أو جشع من سياسة عشوائية ، ومزج سياسات متعددة بشكل عشوائي وما إلى ذلك.
يثبت
إذا لم تقم بتثبيت وكلاء tf حتى الآن ، فقم بتشغيل:
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
تحتوي على المراقبة من البيئة إلى الصفوف (tuple) PolicyStep اسمه يحتوي على الخصائص التالية:
-
action
: العمل ليتم تطبيقها على البيئة. -
state
: ولاية السياسة (على سبيل المثال دولة RNN) ليتم إدخالها في المكالمة التالية إلى العمل. -
info
: معلومات الجانب الاختيارية مثل الاحتمالات سجل العمل.
و time_step_spec
و action_spec
هي مواصفات للخطوة وقت الإدخال والإخراج العمل. لديها سياسات أيضا reset
وظيفة والتي عادة ما تستخدم لإعادة الدولة في سياسات جليل. و 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: سياسة Python المكتوبة
ويلعب سياسة كتابتها الوراء النصي من الإجراءات ممثلة في قائمة (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 نفس الواجهة مثل سياسات Python. دعونا نلقي نظرة على بعض الأمثلة.
مثال 1: سياسة تمويل الإرهاب العشوائية
A 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 ، تم تصميم معظم طبقات الشبكة للعمليات المجمعة ، لذلك نتوقع أن يتم تجميع خطوات الإدخال ، كما سيتم تجميع إخراج الشبكة أيضًا. كما أن الشبكة مسئولة عن إنتاج الإجراءات في النطاق الصحيح من نوع action_spec المحدد. ويتم ذلك باستخدام تقليديا على سبيل المثال تان تنشيط طبقة نهائية لإجراءات المنتجات في [-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_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 افتراضيًا. سيؤدي تعيين هذا إلى "خطأ" إلى إرجاع الإجراءات غير المقصودة التي تنتجها الشبكة.
ويمكن تحويل السياسات العشوائية لسياسات حتمية استخدام، على سبيل المثال، مجمع GreedyPolicy الذي يختار stochastic_policy.distribution().mode()
كما عملها، وتوزيع / دلتا القطعية حول هذا العمل الجشع كما في distribution()
.
مثال 3: سياسة Q
تُستخدم سياسة AQ في وكلاء مثل DQN وتستند إلى شبكة Q التي تتوقع قيمة Q لكل إجراء منفصل. بالنسبة لخطوة زمنية معينة ، فإن توزيع الإجراء في سياسة Q هو توزيع قاطع تم إنشاؤه باستخدام قيم q كسجلات.
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)
مغلفات السياسة
يمكن استخدام غلاف السياسة للالتفاف وتعديل سياسة معينة ، على سبيل المثال إضافة ضوضاء. تعد أغلفة السياسة فئة فرعية من السياسة (Python / TensorFlow) ويمكن بالتالي استخدامها تمامًا مثل أي سياسة أخرى.
مثال: سياسة الجشع
A المجمع الجشع يمكن أن تستخدم لالتفاف أي سياسة 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)