این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

پخش بافرها

مشاهده در TensorFlow.org در Google Colab اجرا کنید مشاهده منبع در GitHub دانلود دفترچه یادداشت

مقدمه

الگوریتم های یادگیری تقویت کننده از بافرهای پخش برای ذخیره مسیرهای تجربه هنگام اجرای خط مشی در یک محیط استفاده می کنند. در حین آموزش ، بافرهای پخش برای زیرمجموعه ای از مسیرها (اعم از یک زیرمجموعه متوالی یا یک نمونه) مورد استعلام قرار می گیرند تا تجربه نماینده را "پخش کنند".

در این colab ، ما دو نوع بافر پخش را بررسی می کنیم: پشتیبانی از پیتون و پشتیبانی از جریان تنش ، به اشتراک گذاری یک API مشترک. در بخش های بعدی ، ما API ، هر یک از پیاده سازی های بافر و نحوه استفاده از آنها را در طول دوره آموزش جمع آوری اطلاعات شرح می دهیم.

برپایی

اگر قبلاً این کار را نکرده اید ، tf-agent ها را نصب کنید.

pip install -q tf-agents
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
import numpy as np

from tf_agents import specs
from tf_agents.agents.dqn import dqn_agent
from tf_agents.drivers import dynamic_step_driver
from tf_agents.environments import suite_gym
from tf_agents.environments import tf_py_environment
from tf_agents.networks import q_network
from tf_agents.replay_buffers import py_uniform_replay_buffer
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.specs import tensor_spec
from tf_agents.trajectories import time_step

tf.compat.v1.enable_v2_behavior()

Replay Buffer API

کلاس Replay Buffer تعریف و روشهای زیر را دارد:

class ReplayBuffer(tf.Module):
  """Abstract base class for TF-Agents replay buffer."""

  def __init__(self, data_spec, capacity):
    """Initializes the replay buffer.

    Args:
      data_spec: A spec or a list/tuple/nest of specs describing
        a single item that can be stored in this buffer
      capacity: number of elements that the replay buffer can hold.
    """

  @property
  def data_spec(self):
    """Returns the spec for items in the replay buffer."""

  @property
  def capacity(self):
    """Returns the capacity of the replay buffer."""

  def add_batch(self, items):
    """Adds a batch of items to the replay buffer."""

  def get_next(self,
               sample_batch_size=None,
               num_steps=None,
               time_stacked=True):
    """Returns an item or batch of items from the buffer."""

  def as_dataset(self,
                 sample_batch_size=None,
                 num_steps=None,
                 num_parallel_calls=None):
    """Creates and returns a dataset that returns entries from the buffer."""


  def gather_all(self):
    """Returns all the items in buffer."""
    return self._gather_all()

  def clear(self):
    """Resets the contents of replay buffer"""

توجه داشته باشید که هنگامی که شی data_spec بافر پخش مجدد مقداردهی اولیه می شود ، به data_spec عناصری که ذخیره خواهد شد نیاز دارد. این مشخصات مربوط به TensorSpec عناصر مسیر است که به بافر اضافه خواهد شد. این مشخصات معمولاً با مشاهده عامل agent.collect_data_spec بدست می agent.collect_data_spec که اشکال ، انواع و ساختارهای مورد انتظار عامل هنگام آموزش را مشخص می کند (بعداً در مورد این اطلاعات بعداً).

TFUniformReplayBuffer

TFUniformReplayBuffer متداول ترین بافر پخش در TF-Agents است ، بنابراین ما در آموزش خود از آن استفاده خواهیم کرد. در TFUniformReplayBuffer ذخیره بافر پشتیبان توسط متغیرهای جریان تنسور انجام می شود و بنابراین بخشی از نمودار محاسبه است.

بافر دسته ای از عناصر را ذخیره می کند و حداکثر ظرفیت حداکثر max_length عناصر را در هر بخش دارد. بنابراین، ظرفیت بافر کل است batch_size X max_length عناصر. عناصر ذخیره شده در بافر باید همه دارای مشخصات داده منطبق باشند. وقتی از بافر پخش برای جمع آوری اطلاعات استفاده می شود ، مشخصات مشخصات داده جمع آوری عامل است.

ایجاد بافر:

برای ایجاد یک TFUniformReplayBuffer ما TFUniformReplayBuffer شویم:

  1. مشخصات عناصر داده ای که بافر ذخیره می کند
  2. batch size مربوط به اندازه دسته بافر
  3. max_length تعداد طول عناصر در هر بخش

در اینجا مثالی از ایجاد TFUniformReplayBuffer با مشخصات داده نمونه ، batch_size 32 و max_length 1000 وجود دارد.

data_spec =  (
        tf.TensorSpec([3], tf.float32, 'action'),
        (
            tf.TensorSpec([5], tf.float32, 'lidar'),
            tf.TensorSpec([3, 2], tf.float32, 'camera')
        )
)

batch_size = 32
max_length = 1000

replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    data_spec,
    batch_size=batch_size,
    max_length=max_length)

نوشتن برای بافر:

برای افزودن عناصر به بافر پخش ، از روش add_batch(items) استفاده می کنیم که در آن items لیست / tuple / لانه تنسورها است که نشان دهنده دسته مواردی است که باید به بافر اضافه شوند. هر عنصر از items باید دارای ابعاد خارجی برابر با اندازه batch_size و ابعاد باقیمانده باید به مشخصات داده مورد (همان مشخصات داده شده به سازنده بافر پخش) متصل باشد.

در اینجا نمونه ای از افزودن دسته ای از موارد وجود دارد

action = tf.constant(1 * np.ones(
    data_spec[0].shape.as_list(), dtype=np.float32))
lidar = tf.constant(
    2 * np.ones(data_spec[1][0].shape.as_list(), dtype=np.float32))
camera = tf.constant(
    3 * np.ones(data_spec[1][1].shape.as_list(), dtype=np.float32))

values = (action, (lidar, camera))
values_batched = tf.nest.map_structure(lambda t: tf.stack([t] * batch_size),
                                       values)

replay_buffer.add_batch(values_batched)

خواندن از بافر

سه روش برای خواندن داده ها از TFUniformReplayBuffer :

  1. get_next() - یک نمونه را از بافر برمی گرداند. اندازه دسته نمونه و تعداد دفعات بازگشت را می توان از طریق استدلال به این روش تعیین کرد.
  2. as_dataset() - بافر پخش را به صورتtf.data.Dataset برمی گرداند. سپس می توان یک تکرار کننده مجموعه داده ایجاد کرد و از طریق نمونه موارد موجود در بافر تکرار کرد.
  3. gather_all() - تمام موارد موجود در بافر را به صورت Tensor با شکل [batch, time, data_spec]

در زیر نمونه هایی از نحوه خواندن از بافر پخش با استفاده از هر یک از این روش ها آورده شده است:

# add more items to the buffer before reading
for _ in range(5):
  replay_buffer.add_batch(values_batched)

# Get one sample from the replay buffer with batch size 10 and 1 timestep:

sample = replay_buffer.get_next(sample_batch_size=10, num_steps=1)

# Convert the replay buffer to a tf.data.Dataset and iterate through it
dataset = replay_buffer.as_dataset(
    sample_batch_size=4,
    num_steps=2)

iterator = iter(dataset)
print("Iterator trajectories:")
trajectories = []
for _ in range(3):
  t, _ = next(iterator)
  trajectories.append(t)

print(tf.nest.map_structure(lambda t: t.shape, trajectories))

# Read all elements in the replay buffer:
trajectories = replay_buffer.gather_all()

print("Trajectories from gather all:")
print(tf.nest.map_structure(lambda t: t.shape, trajectories))
WARNING:tensorflow:From <ipython-input-1-1f9907631cb9>:7: ReplayBuffer.get_next (from tf_agents.replay_buffers.replay_buffer) is deprecated and will be removed in a future version.
Instructions for updating:
Use `as_dataset(..., single_deterministic_pass=False) instead.
Iterator trajectories:
[(TensorShape([4, 2, 3]), (TensorShape([4, 2, 5]), TensorShape([4, 2, 3, 2]))), (TensorShape([4, 2, 3]), (TensorShape([4, 2, 5]), TensorShape([4, 2, 3, 2]))), (TensorShape([4, 2, 3]), (TensorShape([4, 2, 5]), TensorShape([4, 2, 3, 2])))]
WARNING:tensorflow:From <ipython-input-1-1f9907631cb9>:24: ReplayBuffer.gather_all (from tf_agents.replay_buffers.replay_buffer) is deprecated and will be removed in a future version.
Instructions for updating:
Use `as_dataset(..., single_deterministic_pass=True)` instead.
Trajectories from gather all:
(TensorShape([32, 6, 3]), (TensorShape([32, 6, 5]), TensorShape([32, 6, 3, 2])))

PyUniformReplayBuffer

PyUniformReplayBuffer عملکردی مشابه TFUniformReplayBuffer اما به جای متغیرهای tf ، داده های آن در آرایه های numpy ذخیره می شود. از این بافر می توان برای جمع آوری داده های خارج از نمودار استفاده کرد. داشتن حافظه پشتیبان در numpy ممکن است انجام کار دستکاری داده ها (مانند نمایه سازی برای به روزرسانی اولویت ها) را برای برخی از برنامه ها بدون استفاده از متغیرهای Tensorflow آسان کند. با این حال ، این پیاده سازی مزیت بهینه سازی نمودارها با Tensorflow را نخواهد داشت.

در زیر نمونه ای از نمونه سازی PyUniformReplayBuffer از مشخصات خط مشی عامل وجود دارد:

replay_buffer_capacity = 1000*32 # same capacity as the TFUniformReplayBuffer

py_replay_buffer = py_uniform_replay_buffer.PyUniformReplayBuffer(
    capacity=replay_buffer_capacity,
    data_spec=tensor_spec.to_nest_array_spec(data_spec))

استفاده از بافرهای پخش در حین آموزش

اکنون که ما می دانیم چگونه یک بافر پخش مجدد ایجاد کنیم ، مواردی را برای آن بنویسیم و از آن بخوانیم ، می توانیم از آن برای ذخیره مسیرها در حین آموزش عوامل خود استفاده کنیم.

جمع آوری داده ها

ابتدا ، بیایید نحوه استفاده از بافر پخش را هنگام جمع آوری اطلاعات بررسی کنیم.

در TF-Agents برای جمع آوری تجربه در یک محیط از Driver استفاده می کنیم (برای اطلاعات بیشتر به آموزش Driver مراجعه کنید). برای استفاده از Driver ، ما یک Observer تعیین می کنیم که تابعی است که Driver هنگام دریافت مسیر اجرا می کند.

بنابراین ، برای افزودن عناصر مسیر به بافر پخش ، یک ناظر اضافه می کنیم که با اضافه کردن add_batch(items) ، دسته ای از موارد را بر روی بافر پخش پخش می کند.

در زیر مثالی از این با TFUniformReplayBuffer . ما ابتدا یک محیط ، یک شبکه و یک عامل ایجاد می کنیم. سپس یک TFUniformReplayBuffer ایجاد می کنیم. توجه داشته باشید که مشخصات عناصر مسیر در بافر پخش با مشخصات جمع آوری داده عامل برابر است. سپس روش add_batch آن را به عنوان مشاهده گر درایور تنظیم می کنیم که داده های جمع آوری شده را در طول آموزش ما انجام می دهد:

env = suite_gym.load('CartPole-v0')
tf_env = tf_py_environment.TFPyEnvironment(env)

q_net = q_network.QNetwork(
    tf_env.time_step_spec().observation,
    tf_env.action_spec(),
    fc_layer_params=(100,))

agent = dqn_agent.DqnAgent(
    tf_env.time_step_spec(),
    tf_env.action_spec(),
    q_network=q_net,
    optimizer=tf.compat.v1.train.AdamOptimizer(0.001))

replay_buffer_capacity = 1000

replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    agent.collect_data_spec,
    batch_size=tf_env.batch_size,
    max_length=replay_buffer_capacity)

# Add an observer that adds to the replay buffer:
replay_observer = [replay_buffer.add_batch]

collect_steps_per_iteration = 10
collect_op = dynamic_step_driver.DynamicStepDriver(
  tf_env,
  agent.collect_policy,
  observers=replay_observer,
  num_steps=collect_steps_per_iteration).run()
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tf_agents/drivers/dynamic_step_driver.py:203: calling while_loop_v2 (from tensorflow.python.ops.control_flow_ops) with back_prop=False is deprecated and will be removed in a future version.
Instructions for updating:
back_prop=False is deprecated. Consider using tf.stop_gradient instead.
Instead of:
results = tf.while_loop(c, b, vars, back_prop=False)
Use:
results = tf.nest.map_structure(tf.stop_gradient, tf.while_loop(c, b, vars))

خواندن داده ها برای یک مرحله قطار

پس از افزودن عناصر مسیر به بافر پخش ، می توانیم دسته ای از مسیرها را از بافر پخش بخوانیم تا به عنوان داده های ورودی برای یک مرحله قطار استفاده کنیم.

در اینجا مثالی از نحوه آموزش مسیرها از بافر پخش در یک حلقه آموزش آورده شده است:

# Read the replay buffer as a Dataset,
# read batches of 4 elements, each with 2 timesteps:
dataset = replay_buffer.as_dataset(
    sample_batch_size=4,
    num_steps=2)

iterator = iter(dataset)

num_train_steps = 10

for _ in range(num_train_steps):
  trajectories, _ = next(iterator)
  loss = agent.train(experience=trajectories)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/util/dispatch.py:201: calling foldr_v2 (from tensorflow.python.ops.functional_ops) with back_prop=False is deprecated and will be removed in a future version.
Instructions for updating:
back_prop=False is deprecated. Consider using tf.stop_gradient instead.
Instead of:
results = tf.foldr(fn, elems, back_prop=False)
Use:
results = tf.nest.map_structure(tf.stop_gradient, tf.foldr(fn, elems))