דף זה תורגם על ידי Cloud Translation API.
Switch to English

הפעל מחדש מאגרים

צפה ב- TensorFlow.org הפעל בגוגל קולאב צפה במקור ב- GitHub הורד מחברת

מבוא

אלגוריתמי למידת חיזוק משתמשים במאגרי הפעלה חוזרת כדי לאחסן מסלולי ניסיון בעת ​​ביצוע מדיניות בסביבה. במהלך האימון, מאגרי השידור החוזר נשאלים עבור קבוצת משנה של המסלולים (או קבוצת משנה רצופה או מדגם) כדי "לחזור" על חוויית הסוכן.

במכלאה זו, אנו חוקרים שני סוגים של מאגרי הפעלה חוזרת: מגובה פיתון ומגובה זרימת טנזור, חולקים ממשק API משותף. בסעיפים הבאים אנו מתארים את ה- API, כל אחת מיישומי המאגר וכיצד להשתמש בהם במהלך אימון לאיסוף נתונים.

להכין

התקן סוכני tf אם עדיין לא עשית זאת.

pip install -q tf-agents
pip install -q gym
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()

ממשק API של Buffer Replay

המחלקה 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-Agents, ולכן נשתמש בו במדריך שלנו כאן. ב- TFUniformReplayBuffer אחסון מאגר הגיבוי נעשה על ידי משתני זרימת טנסור ולכן הוא חלק מגרף החישוב.

המאגר מאחסן קבוצות של אלמנטים ויש לו קיבולת max_length רכיבי max_length מקסימום לכל קטע אצווה. לפיכך, קיבולת המאגר הכוללת הינה batch_size x רכיבי max_length האלמנטים המאוחסנים במאגר חייבים לכלול מפרט נתונים תואם. כאשר נעשה שימוש במאגר ההפעלה החוזרת לאיסוף נתונים, המפרט הוא מפרט נתוני האיסוף של הסוכן.

יצירת המאגר:

כדי ליצור TFUniformReplayBuffer אנו מעבירים:

  1. המפרט של רכיבי הנתונים שהמאגר יאחסן
  2. batch size המתאים לגודל האצווה של המאגר
  3. המספר max_length של 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) החוזרת, אנו משתמשים בשיטת add_batch(items) כאשר items הם רשימה / tuple / קן של טנזורים המייצגים את אצוות הפריטים שיש להוסיף למאגר. על כל רכיב items להיות בעל מימד חיצוני השווה batch_size , batch_size הנותרים חייבים לדבוק במפרט הנתונים של הפריט (זהה למפרט הנתונים 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() - מחזיר דוגמה אחת get_next() . ניתן לציין את גודל אצווה המדגם ואת מספר פעולות הזמן שהוחזרו באמצעות טיעונים לשיטה זו.
  2. as_dataset() - מחזיר את חיץtf.data.Dataset החוזרת כ-tf.data.Dataset . לאחר מכן ניתן ליצור איטרטור של מערך נתונים ולבצע איטרציה דרך הדגימות של הפריטים במאגר.
  3. gather_all() - מחזיר את כל הפריטים במאגר כטנסור עם צורה [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, הנתונים שלו מאוחסנים במערכים קהים. ניתן להשתמש במאגר זה לאיסוף נתונים מחוץ לתרשים. אחסון הגיבוי חסר תחושה עשוי להקל על יישומים מסוימים לבצע מניפולציה בנתונים (כגון אינדקס לצורך עדכון סדרי עדיפויות) מבלי להשתמש במשתני 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) כדי להוסיף אצווה של פריטים במאגר 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))