কপিরাইট 2021 টিএফ-এজেন্ট লেখক।
TensorFlow.org এ দেখুন | Google Colab-এ চালান | GitHub-এ উৎস দেখুন | নোটবুক ডাউনলোড করুন |
ভূমিকা
নিচের উদাহরনের মাধ্যমে দেখানো কিভাবে প্রশিক্ষণের শ্রেণীগত DQN (C51) মেমরি-এজেন্ট লাইব্রেরি ব্যবহার Cartpole পরিবেশের উপর এজেন্ট।
নিশ্চিত করুন যে আপনি মাধ্যমে একবার দেখুন করুন DQN টিউটোরিয়াল একটি পূর্বশর্ত হিসাবে। এই টিউটোরিয়ালটি DQN টিউটোরিয়ালের সাথে পরিচিত হবে; এটি প্রধানত DQN এবং C51 এর মধ্যে পার্থক্যের উপর ফোকাস করবে।
সেটআপ
আপনি যদি এখনও tf-এজেন্ট ইনস্টল না করে থাকেন, তাহলে চালান:
sudo apt-get update
sudo apt-get install -y xvfb ffmpeg freeglut3-dev
pip install 'imageio==2.4.0'
pip install pyvirtualdisplay
pip install tf-agents
pip install pyglet
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import base64
import imageio
import IPython
import matplotlib
import matplotlib.pyplot as plt
import PIL.Image
import pyvirtualdisplay
import tensorflow as tf
from tf_agents.agents.categorical_dqn import categorical_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.eval import metric_utils
from tf_agents.metrics import tf_metrics
from tf_agents.networks import categorical_q_network
from tf_agents.policies import random_tf_policy
from tf_agents.replay_buffers import tf_uniform_replay_buffer
from tf_agents.trajectories import trajectory
from tf_agents.utils import common
# Set up a virtual display for rendering OpenAI gym environments.
display = pyvirtualdisplay.Display(visible=0, size=(1400, 900)).start()
হাইপারপ্যারামিটার
env_name = "CartPole-v1" # @param {type:"string"}
num_iterations = 15000 # @param {type:"integer"}
initial_collect_steps = 1000 # @param {type:"integer"}
collect_steps_per_iteration = 1 # @param {type:"integer"}
replay_buffer_capacity = 100000 # @param {type:"integer"}
fc_layer_params = (100,)
batch_size = 64 # @param {type:"integer"}
learning_rate = 1e-3 # @param {type:"number"}
gamma = 0.99
log_interval = 200 # @param {type:"integer"}
num_atoms = 51 # @param {type:"integer"}
min_q_value = -20 # @param {type:"integer"}
max_q_value = 20 # @param {type:"integer"}
n_step_update = 2 # @param {type:"integer"}
num_eval_episodes = 10 # @param {type:"integer"}
eval_interval = 1000 # @param {type:"integer"}
পরিবেশ
আগের মতো পরিবেশ লোড করুন, একটি প্রশিক্ষণের জন্য এবং একটি মূল্যায়নের জন্য। এখানে আমরা CartPole-v1 (DQN টিউটোরিয়ালে বনাম CartPole-v0) ব্যবহার করি, যার সর্বোচ্চ পুরষ্কার 200 এর পরিবর্তে 500 এর বেশি।
train_py_env = suite_gym.load(env_name)
eval_py_env = suite_gym.load(env_name)
train_env = tf_py_environment.TFPyEnvironment(train_py_env)
eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)
প্রতিনিধি
C51 হল DQN এর উপর ভিত্তি করে একটি Q-লার্নিং অ্যালগরিদম। ডিকিউএন-এর মতো, এটি একটি বিচ্ছিন্ন অ্যাকশন স্পেস সহ যেকোনো পরিবেশে ব্যবহার করা যেতে পারে।
C51 এবং DQN এর মধ্যে প্রধান পার্থক্য হল প্রতিটি স্টেট-অ্যাকশন পেয়ারের জন্য Q-মান ভবিষ্যদ্বাণী করার পরিবর্তে, C51 Q-মানের সম্ভাব্যতা বিতরণের জন্য একটি হিস্টোগ্রাম মডেলের ভবিষ্যদ্বাণী করে:
প্রত্যাশিত মানের পরিবর্তে বিতরণ শেখার মাধ্যমে, অ্যালগরিদম প্রশিক্ষণের সময় আরও স্থিতিশীল থাকতে সক্ষম হয়, যার ফলে চূড়ান্ত কর্মক্ষমতা উন্নত হয়। এটি বিমোডাল বা এমনকি মাল্টিমোডাল মান বিতরণের পরিস্থিতিতে বিশেষভাবে সত্য, যেখানে একটি একক গড় একটি সঠিক চিত্র প্রদান করে না।
মানের পরিবর্তে সম্ভাব্যতা বণ্টনের উপর প্রশিক্ষণের জন্য, C51 এর ক্ষতির ফাংশন গণনা করার জন্য কিছু জটিল বন্টন গণনা করতে হবে। কিন্তু চিন্তা করবেন না, TF-এজেন্টে আপনার জন্য এই সমস্ত যত্ন নেওয়া হয়!
একটি C51 এজেন্ট তৈরি করতে হলে, আমরা প্রথমে একটি তৈরি করতে হবে CategoricalQNetwork
। এর এপিআই CategoricalQNetwork
যে একই হয় QNetwork
ছাড়া যে একটি অতিরিক্ত যুক্তি num_atoms
। এটি আমাদের সম্ভাব্যতা বন্টন অনুমানে সমর্থন পয়েন্টের সংখ্যা প্রতিনিধিত্ব করে। (উপরের চিত্রটিতে 10টি সমর্থন পয়েন্ট রয়েছে, প্রতিটি একটি উল্লম্ব নীল দণ্ড দ্বারা উপস্থাপিত।) আপনি নাম থেকে বলতে পারেন, পরমাণুর ডিফল্ট সংখ্যা 51।
categorical_q_net = categorical_q_network.CategoricalQNetwork(
train_env.observation_spec(),
train_env.action_spec(),
num_atoms=num_atoms,
fc_layer_params=fc_layer_params)
আমরা একটি প্রয়োজন optimizer
নেটওয়ার্কের আমরা শুধু নির্মিত প্রশিক্ষণের, এবং একটি train_step_counter
কতবার নেটওয়ার্কের আপডেট করা হয়েছে ট্র্যাক রাখতে পরিবর্তনশীল।
নোট ভ্যানিলা থেকে অন্য একটি গুরুত্বপূর্ণ পার্থক্য যে DqnAgent
যে আমরা এখন নির্দিষ্ট করতে হবে হয় min_q_value
এবং max_q_value
আর্গুমেন্ট হিসাবে। এগুলি সমর্থনের সর্বাধিক চরম মানগুলি নির্দিষ্ট করে (অন্য কথায়, উভয় পাশে 51টি পরমাণুর মধ্যে সবচেয়ে চরম)। আপনার নির্দিষ্ট পরিবেশের জন্য যথাযথভাবে এগুলি বেছে নেওয়ার বিষয়টি নিশ্চিত করুন। এখানে আমরা -20 এবং 20 ব্যবহার করি।
optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=learning_rate)
train_step_counter = tf.Variable(0)
agent = categorical_dqn_agent.CategoricalDqnAgent(
train_env.time_step_spec(),
train_env.action_spec(),
categorical_q_network=categorical_q_net,
optimizer=optimizer,
min_q_value=min_q_value,
max_q_value=max_q_value,
n_step_update=n_step_update,
td_errors_loss_fn=common.element_wise_squared_loss,
gamma=gamma,
train_step_counter=train_step_counter)
agent.initialize()
নোটটিতে একটা শেষ জিনিস যে আমরা সাথে ব্যবহারের এন-পদক্ষেপ আপডেটগুলিতে একটি আর্গুমেন্ট জুড়েছি \(n\) = 2. একক-পদক্ষেপ প্রশ্ন-লার্নিং (ইন\(n\) = 1), আমরা শুধুমাত্র কিউ-মানের মধ্যে ত্রুটি গনা বর্তমান সময়ে ধাপে এবং পরবর্তী সময়ে একক-পদক্ষেপ রিটার্ন ব্যবহার করে (বেলম্যান অপ্টিম্যালিটি সমীকরণের উপর ভিত্তি করে)। একক-পদক্ষেপ রিটার্ন হিসাবে সংজ্ঞায়িত করা হয়:
\(G_t = R_{t + 1} + \gamma V(s_{t + 1})\)
যেখানে আমরা সংজ্ঞায়িত \(V(s) = \max_a{Q(s, a)}\)।
এন-পদক্ষেপ আপডেট মান একক-পদক্ষেপ রিটার্ন ফাংশন বিস্তৃত জড়িত \(n\) সময়:
\(G_t^n = R_{t + 1} + \gamma R_{t + 2} + \gamma^2 R_{t + 3} + \dots + \gamma^n V(s_{t + n})\)
এন-পদক্ষেপ আপডেট ভবিষ্যতে আরও থেকে বুটস্ট্র্যাপ করতে এজেন্ট সক্ষম এবং ডান মান \(n\), দ্রুত শেখার এই প্রায়ই বাড়ে।
যদিও C51 এবং n-পদক্ষেপ আপডেট প্রায়ই অগ্রাধিকারের রিপ্লে কোর গঠনের সঙ্গে মিলিত হয় রেনবো এজেন্ট , আমরা অগ্রাধিকারের রিপ্লে বাস্তবায়ন থেকে কোনো পরিমাপযোগ্য উন্নতি দেখেছি। তাছাড়া, আমরা দেখতে পাই যে আমাদের C51 এজেন্টকে n-স্টেপ আপডেটের সাথে একত্রিত করার সময়, আমাদের এজেন্টের পাশাপাশি অন্যান্য রেনবো এজেন্টরাও পারফর্ম করে আমরা যে আটারি পরিবেশের নমুনা পরীক্ষা করেছি।
মেট্রিক্স এবং মূল্যায়ন
একটি নীতি মূল্যায়ন করতে ব্যবহৃত সবচেয়ে সাধারণ মেট্রিক হল গড় রিটার্ন। রিটার্ন হল একটি পর্বের জন্য একটি পরিবেশে একটি নীতি চালানোর সময় প্রাপ্ত পুরষ্কারের সমষ্টি এবং আমরা সাধারণত এটিকে কয়েকটি পর্বে গড় করি। আমরা নিম্নরূপ গড় রিটার্ন মেট্রিক গণনা করতে পারি।
def compute_avg_return(environment, policy, num_episodes=10):
total_return = 0.0
for _ in range(num_episodes):
time_step = environment.reset()
episode_return = 0.0
while not time_step.is_last():
action_step = policy.action(time_step)
time_step = environment.step(action_step.action)
episode_return += time_step.reward
total_return += episode_return
avg_return = total_return / num_episodes
return avg_return.numpy()[0]
random_policy = random_tf_policy.RandomTFPolicy(train_env.time_step_spec(),
train_env.action_spec())
compute_avg_return(eval_env, random_policy, num_eval_episodes)
# Please also see the metrics module for standard implementations of different
# metrics.
20.0
তথ্য সংগ্রহ
DQN টিউটোরিয়ালের মতো, র্যান্ডম নীতির সাথে রিপ্লে বাফার এবং প্রাথমিক ডেটা সংগ্রহ সেট আপ করুন।
replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
data_spec=agent.collect_data_spec,
batch_size=train_env.batch_size,
max_length=replay_buffer_capacity)
def collect_step(environment, policy):
time_step = environment.current_time_step()
action_step = policy.action(time_step)
next_time_step = environment.step(action_step.action)
traj = trajectory.from_transition(time_step, action_step, next_time_step)
# Add trajectory to the replay buffer
replay_buffer.add_batch(traj)
for _ in range(initial_collect_steps):
collect_step(train_env, random_policy)
# This loop is so common in RL, that we provide standard implementations of
# these. For more details see the drivers module.
# Dataset generates trajectories with shape [BxTx...] where
# T = n_step_update + 1.
dataset = replay_buffer.as_dataset(
num_parallel_calls=3, sample_batch_size=batch_size,
num_steps=n_step_update + 1).prefetch(3)
iterator = iter(dataset)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/data/experimental/ops/counter.py:66: scan (from tensorflow.python.data.experimental.ops.scan_ops) is deprecated and will be removed in a future version. Instructions for updating: Use `tf.data.Dataset.scan(...) instead WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/autograph/impl/api.py:382: 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.
এজেন্ট প্রশিক্ষণ
প্রশিক্ষণ লুপে পরিবেশ থেকে তথ্য সংগ্রহ এবং এজেন্টের নেটওয়ার্ক অপ্টিমাইজ করা উভয়ই জড়িত। পথের পাশাপাশি, আমরা কীভাবে কাজ করছি তা দেখতে আমরা মাঝে মাঝে এজেন্টের নীতি মূল্যায়ন করব।
নিম্নলিখিতটি চালাতে ~7 মিনিট সময় লাগবে।
try:
%%time
except:
pass
# (Optional) Optimize by wrapping some of the code in a graph using TF function.
agent.train = common.function(agent.train)
# Reset the train step
agent.train_step_counter.assign(0)
# Evaluate the agent's policy once before training.
avg_return = compute_avg_return(eval_env, agent.policy, num_eval_episodes)
returns = [avg_return]
for _ in range(num_iterations):
# Collect a few steps using collect_policy and save to the replay buffer.
for _ in range(collect_steps_per_iteration):
collect_step(train_env, agent.collect_policy)
# Sample a batch of data from the buffer and update the agent's network.
experience, unused_info = next(iterator)
train_loss = agent.train(experience)
step = agent.train_step_counter.numpy()
if step % log_interval == 0:
print('step = {0}: loss = {1}'.format(step, train_loss.loss))
if step % eval_interval == 0:
avg_return = compute_avg_return(eval_env, agent.policy, num_eval_episodes)
print('step = {0}: Average Return = {1:.2f}'.format(step, avg_return))
returns.append(avg_return)
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/util/dispatch.py:206: 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)) step = 200: loss = 3.199000597000122 step = 400: loss = 2.083357810974121 step = 600: loss = 1.9901162385940552 step = 800: loss = 1.9055049419403076 step = 1000: loss = 1.7382612228393555 step = 1000: Average Return = 34.40 step = 1200: loss = 1.3624987602233887 step = 1400: loss = 1.548039197921753 step = 1600: loss = 1.4193217754364014 step = 1800: loss = 1.3339967727661133 step = 2000: loss = 1.1471226215362549 step = 2000: Average Return = 91.10 step = 2200: loss = 1.360352873802185 step = 2400: loss = 1.4253160953521729 step = 2600: loss = 0.9550995826721191 step = 2800: loss = 0.9822611808776855 step = 3000: loss = 1.0512573719024658 step = 3000: Average Return = 102.60 step = 3200: loss = 1.131516456604004 step = 3400: loss = 1.0834283828735352 step = 3600: loss = 0.8771724104881287 step = 3800: loss = 0.7854692935943604 step = 4000: loss = 0.7451740503311157 step = 4000: Average Return = 179.10 step = 4200: loss = 0.6963338851928711 step = 4400: loss = 0.8579068183898926 step = 4600: loss = 0.735978364944458 step = 4800: loss = 0.5723521709442139 step = 5000: loss = 0.6422518491744995 step = 5000: Average Return = 138.00 step = 5200: loss = 0.5242955684661865 step = 5400: loss = 0.869032621383667 step = 5600: loss = 0.7798122763633728 step = 5800: loss = 0.745892345905304 step = 6000: loss = 0.7540864944458008 step = 6000: Average Return = 155.80 step = 6200: loss = 0.6851651668548584 step = 6400: loss = 0.7417727112770081 step = 6600: loss = 0.7385923862457275 step = 6800: loss = 0.8823254108428955 step = 7000: loss = 0.6216408014297485 step = 7000: Average Return = 146.90 step = 7200: loss = 0.3905255198478699 step = 7400: loss = 0.5030156373977661 step = 7600: loss = 0.6326021552085876 step = 7800: loss = 0.6071780920028687 step = 8000: loss = 0.49069637060165405 step = 8000: Average Return = 332.70 step = 8200: loss = 0.7194125056266785 step = 8400: loss = 0.7707428932189941 step = 8600: loss = 0.42258384823799133 step = 8800: loss = 0.5215793251991272 step = 9000: loss = 0.6949542164802551 step = 9000: Average Return = 174.10 step = 9200: loss = 0.7312793731689453 step = 9400: loss = 0.5663323402404785 step = 9600: loss = 0.8518731594085693 step = 9800: loss = 0.5256152153015137 step = 10000: loss = 0.578148603439331 step = 10000: Average Return = 147.40 step = 10200: loss = 0.46965712308883667 step = 10400: loss = 0.5685954093933105 step = 10600: loss = 0.5819060802459717 step = 10800: loss = 0.792033851146698 step = 11000: loss = 0.5804982781410217 step = 11000: Average Return = 186.80 step = 11200: loss = 0.4973406195640564 step = 11400: loss = 0.33229681849479675 step = 11600: loss = 0.5267124176025391 step = 11800: loss = 0.585414469242096 step = 12000: loss = 0.6697092652320862 step = 12000: Average Return = 135.30 step = 12200: loss = 0.30732017755508423 step = 12400: loss = 0.490392804145813 step = 12600: loss = 0.28014713525772095 step = 12800: loss = 0.456543892621994 step = 13000: loss = 0.48237597942352295 step = 13000: Average Return = 182.70 step = 13200: loss = 0.5447070598602295 step = 13400: loss = 0.4602382481098175 step = 13600: loss = 0.5659506320953369 step = 13800: loss = 0.47906267642974854 step = 14000: loss = 0.4060840904712677 step = 14000: Average Return = 153.00 step = 14200: loss = 0.6457054018974304 step = 14400: loss = 0.4795544147491455 step = 14600: loss = 0.16895757615566254 step = 14800: loss = 0.5005109906196594 step = 15000: loss = 0.5339224338531494 step = 15000: Average Return = 165.10
ভিজ্যুয়ালাইজেশন
প্লট
আমাদের এজেন্টের পারফরম্যান্স দেখার জন্য আমরা রিটার্ন বনাম বিশ্বব্যাপী পদক্ষেপের পরিকল্পনা করতে পারি। ইন Cartpole-v1
, পরিবেশ +1 টি একটি পুরস্কার প্রত্যেক সময় ধাপের জন্য মেরু থাকার বিষয়টি মতেই মানেনা এবং যেহেতু ধাপের সর্বোচ্চ সংখ্যক 500, সর্বোচ্চ সম্ভব আগমন এছাড়াও 500।
steps = range(0, num_iterations + 1, eval_interval)
plt.plot(steps, returns)
plt.ylabel('Average Return')
plt.xlabel('Step')
plt.ylim(top=550)
(19.485000991821288, 550.0)
ভিডিও
প্রতিটি ধাপে পরিবেশ রেন্ডার করে একটি এজেন্টের কর্মক্ষমতা কল্পনা করা সহায়ক। এটি করার আগে, আসুন প্রথমে এই কোল্যাবে ভিডিও এম্বেড করার জন্য একটি ফাংশন তৈরি করি।
def embed_mp4(filename):
"""Embeds an mp4 file in the notebook."""
video = open(filename,'rb').read()
b64 = base64.b64encode(video)
tag = '''
<video width="640" height="480" controls>
<source src="data:video/mp4;base64,{0}" type="video/mp4">
Your browser does not support the video tag.
</video>'''.format(b64.decode())
return IPython.display.HTML(tag)
নিম্নলিখিত কোডটি কয়েকটি পর্বের জন্য এজেন্টের নীতিকে কল্পনা করে:
num_episodes = 3
video_filename = 'imageio.mp4'
with imageio.get_writer(video_filename, fps=60) as video:
for _ in range(num_episodes):
time_step = eval_env.reset()
video.append_data(eval_py_env.render())
while not time_step.is_last():
action_step = agent.policy.action(time_step)
time_step = eval_env.step(action_step.action)
video.append_data(eval_py_env.render())
embed_mp4(video_filename)
WARNING:root:IMAGEIO FFMPEG_WRITER WARNING: input image is not divisible by macro_block_size=16, resizing from (400, 600) to (400, 608) to ensure video compatibility with most codecs and players. To prevent resizing, make your input image divisible by the macro_block_size or set the macro_block_size to None (risking incompatibility). You may also see a FFMPEG warning concerning speedloss due to data not being aligned. [swscaler @ 0x5646eec183c0] Warning: data is not aligned! This can lead to a speed loss
C51 CartPole-v1-এ DQN-এর থেকে কিছুটা ভালো করার প্রবণতা দেখায়, কিন্তু ক্রমবর্ধমান জটিল পরিবেশে দুটি এজেন্টের মধ্যে পার্থক্য আরও বেশি উল্লেখযোগ্য হয়ে ওঠে। উদাহরণস্বরূপ, সম্পূর্ণ Atari 2600 বেঞ্চমার্কে, C51 একটি র্যান্ডম এজেন্টের ক্ষেত্রে স্বাভাবিক করার পরে DQN-এর তুলনায় 126% গড় স্কোরের উন্নতি দেখায়। n-ধাপে আপডেটগুলি অন্তর্ভুক্ত করে অতিরিক্ত উন্নতি লাভ করা যেতে পারে।
C51 অ্যালগরিদম মধ্যে একটি গভীর ডুব জন্য, দেখুন অতিরিক্ত শিক্ষা সংযোজন (2017) ওপর Distributional পরিপ্রেক্ষিত ।