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

پخش مجدد بافرها

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

مقدمه

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

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

برپایی

اگر قبلاً کار نکرده اید ، عوامل tf را نصب کنید.

pip install -q --pre tf-agents[reverb]
pip install -q gym
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.
WARNING: You are using pip version 20.1.1; however, version 20.2 is available.
You should consider upgrading via the '/tmpfs/src/tf_docs_env/bin/python -m pip install --upgrade pip' command.

 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 عناصر ذخیره شده نیاز دارد. این مشخصات مربوط به TensorSpec عناصر مسیر است که به بافر اضافه می شود. این مشخصات معمولاً با مراجعه به نماینده عامل انجام می شود. agent.collect_data_spec که اشکال ، انواع و ساختارهایی را که در زمان آموزش انتظار می رود توسط عامل تعیین می کند (بیشتر در مورد بعد)

TFUniformReplayBuffer

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

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

ایجاد بافر:

برای ایجاد یک 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 یک لیست / توپل / لانه تنور که نماینده دسته مواردی است که باید به بافر اضافه شود. هر عنصر از 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-6-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-6-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 ممکن است کار را برای دستکاری داده ها (مانند ایندکس کردن برای به روز کردن اولویت ها) بدون استفاده از متغیرهای 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 ، یک Observer مشخص می كنیم كه یك تابع برای Driver كه هنگام دریافت مسیر می تواند اجرای آن را انجام دهد.

بنابراین ، برای اضافه کردن عناصر مسیر به بافر پخش مجدد ، ما یک ناظر را اضافه می کنیم که با اضافه کردن add_batch(items) برای اضافه کردن 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)