Chính sách

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải xuống sổ ghi chép

Giới thiệu

Trong thuật ngữ Học tăng cường, các chính sách ánh xạ một quan sát từ môi trường đến một hành động hoặc sự phân bổ qua các hành động. Trong TF-Đại lý, quan sát từ môi trường được chứa trong một tuple tên TimeStep('step_type', 'discount', 'reward', 'observation') , và chính sách bản đồ timesteps đến những hành động hoặc các bản phân phối qua hành động. Hầu hết các chính sách sử dụng timestep.observation , một số chính sách sử dụng timestep.step_type (ví dụ để thiết lập lại trạng thái ở phần đầu của một tập phim trong chính sách stateful), nhưng timestep.discounttimestep.reward thường bị bỏ qua.

Các chính sách có liên quan đến các thành phần khác trong TF-Agents theo cách sau. Hầu hết các chính sách đều có mạng nơ-ron để tính toán các hành động và / hoặc phân phối qua các hành động từ TimeSteps. Tác nhân có thể chứa một hoặc nhiều chính sách cho các mục đích khác nhau, ví dụ: chính sách chính đang được đào tạo để triển khai và chính sách ồn ào để thu thập dữ liệu. Các chính sách có thể được lưu / khôi phục và có thể được sử dụng một cách bí mật của tác nhân để thu thập dữ liệu, đánh giá, v.v.

Một số chính sách dễ viết hơn trong Tensorflow (ví dụ: những chính sách có mạng nơron), trong khi những chính sách khác dễ viết hơn bằng Python (ví dụ: theo một tập lệnh các hành động). Vì vậy, trong các tác nhân TF, chúng tôi cho phép cả chính sách Python và Tensorflow. Hơn nữa, các chính sách được viết bằng TensorFlow có thể phải được sử dụng trong môi trường Python hoặc ngược lại, ví dụ: chính sách TensorFlow được sử dụng để đào tạo nhưng sau đó được triển khai trong môi trường Python sản xuất. Để làm cho việc này dễ dàng hơn, chúng tôi cung cấp các trình bao bọc để chuyển đổi giữa các chính sách Python và TensorFlow.

Một loại chính sách thú vị khác là trình bao bọc chính sách, nó sửa đổi một chính sách nhất định theo một cách nhất định, ví dụ: thêm một loại nhiễu cụ thể, tạo phiên bản tham lam hoặc tham lam của chính sách ngẫu nhiên, kết hợp ngẫu nhiên nhiều chính sách, v.v.

Thành lập

Nếu bạn chưa cài đặt tf-agent, hãy chạy:

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

Chính sách Python

Giao diện cho các chính sách Python được định nghĩa trong policies/py_policy.PyPolicy . Các phương pháp chính là:

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

Phương pháp quan trọng nhất là action(time_step) mà bản đồ một time_step chứa một quan sát từ môi trường đến một tuple PolicyStep tên có chứa các thuộc tính sau:

  • action : Hành động được áp dụng đối với môi trường.
  • state : Trạng thái của chính sách (ví dụ như nhà nước RNN) được đưa vào các cuộc gọi tiếp theo để hành động.
  • info : Thông tin bên bắt buộc như xác suất log hành động.

Các time_step_specaction_spec là thông số kỹ thuật cho lần bước đầu vào và đầu ra hành động. Chính sách này cũng có một reset chức năng mà thường được sử dụng để đặt lại nhà nước trong chính sách stateful. Các update(new_policy) chức năng cập nhật self đối với new_policy .

Bây giờ, chúng ta hãy xem xét một vài ví dụ về các chính sách Python.

Ví dụ 1: Chính sách Python ngẫu nhiên

Một ví dụ đơn giản của một PyPolicyRandomPyPolicy mà tạo ra những hành động ngẫu nhiên cho rời rạc / action_spec được liên tục. Các đầu vào time_step được bỏ qua.

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=())

Ví dụ 2: Chính sách Python được tập lệnh

Một vở kịch chính sách kịch bản sao lưu một kịch bản hành động thể hiện dưới dạng một danh sách (num_repeats, action) tuples. Mỗi lần các action hàm được gọi, nó sẽ trả về các hành động tiếp theo trong danh sách cho đến khi số quy định của lặp đi lặp lại được thực hiện, và sau đó chuyển sang các hành động tiếp theo trong danh sách. Các reset phương pháp có thể được gọi để bắt đầu thực hiện từ đầu danh sách.

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=())

Chính sách TensorFlow

Các chính sách TensorFlow tuân theo giao diện giống như các chính sách Python. Chúng ta hãy xem xét một vài ví dụ.

Ví dụ 1: Chính sách TF ngẫu nhiên

Một RandomTFPolicy thể được sử dụng để tạo ra những hành động ngẫu nhiên theo một rời rạc cho / liên tục action_spec . Các đầu vào time_step được bỏ qua.

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)

Ví dụ 2: Chính sách Tác nhân

Một chính sách diễn viên có thể được tạo ra bằng cách sử dụng một mạng lưới mà các bản đồ time_steps để hành động hoặc một mạng lưới mà các bản đồ time_steps để phân phối qua hành động.

Sử dụng mạng hành động

Hãy để chúng tôi xác định một mạng như sau:

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

Trong TensorFlow, hầu hết các lớp mạng được thiết kế cho các hoạt động hàng loạt, vì vậy chúng tôi mong đợi các bước thời gian đầu vào sẽ được thực hiện theo từng đợt và đầu ra của mạng cũng sẽ được thực hiện theo từng đợt. Ngoài ra, mạng chịu trách nhiệm tạo ra các hành động trong phạm vi chính xác của action_spec đã cho. Đây là thông thường thực hiện bằng ví dụ một tanh kích hoạt cho các lớp cuối cùng để hành động sản trong [-1, 1] và sau đó mở rộng quy mô và thay đổi này đến phạm vi đúng như action_spec đầu vào (ví dụ thấy tf_agents/agents/ddpg/networks.actor_network() ).

Bây giờ, chúng ta có thể tạo chính sách tác nhân bằng cách sử dụng mạng trên.

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)

Chúng tôi có thể áp dụng nó cho bất kỳ lô thời gian nào tuân theo 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)

Trong ví dụ trên, chúng tôi đã tạo chính sách bằng cách sử dụng mạng hành động tạo ra một bộ căng hành động. Trong trường hợp này, policy.distribution(time_step) là một xác định (đồng bằng) phân phối xung quanh đầu ra của policy.action(time_step) . Một cách để tạo ra chính sách ngẫu nhiên là bao bọc chính sách tác nhân trong một trình bao bọc chính sách để tạo thêm nhiễu cho các hành động. Một cách khác là tạo chính sách tác nhân bằng cách sử dụng mạng phân phối hành động thay vì mạng hành động như hình dưới đây.

Sử dụng mạng phân phối hành động

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)

Lưu ý rằng trong phần trên, các hành động được cắt theo phạm vi của thông số hành động đã cho [-1, 1]. Điều này là do một đối số phương thức khởi tạo của ActorPolicy clip = True theo mặc định. Đặt giá trị này thành false sẽ trả về các hành động không liên quan do mạng tạo ra.

Chính sách Stochastic có thể được chuyển đổi sang chính sách xác định sử dụng, ví dụ, một wrapper GreedyPolicy mà chọn stochastic_policy.distribution().mode() như hành động của nó, và một bản phân phối / đồng bằng xác định xung quanh hành động tham lam này như nó distribution() .

Ví dụ 3: Chính sách Q

Chính sách AQ được sử dụng trong các đại lý như DQN và dựa trên mạng Q dự đoán giá trị Q cho mỗi hành động rời rạc. Đối với một bước thời gian nhất định, phân phối hành động trong Chính sách Q là một phân phối phân loại được tạo bằng cách sử dụng các giá trị q làm logits.

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)

Trình gói chính sách

Một trình bao bọc chính sách có thể được sử dụng để bao bọc và sửa đổi một chính sách nhất định, ví dụ như thêm nhiễu. Trình bao bọc chính sách là một lớp con của Chính sách (Python / TensorFlow) và do đó có thể được sử dụng giống như bất kỳ chính sách nào khác.

Ví dụ: Chính sách tham lam

Một wrapper tham lam có thể được sử dụng để quấn bất kỳ chính sách TensorFlow rằng dụng cụ distribution() . GreedyPolicy.action() sẽ trở lại wrapped_policy.distribution().mode()GreedyPolicy.distribution() là một phân phối / đồng bằng xác định xung quanh 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)