Trainieren Sie ein Deep Q-Netzwerk mit TF-Agenten

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigenNotizbuch herunterladen

Einführung

Dieses Beispiel zeigt, wie Sie einen DQN-Agenten (Deep Q Networks) in der Cartpole-Umgebung mit der TF-Agents-Bibliothek trainieren.

Cartpole-Umgebung

Es führt Sie durch alle Komponenten einer Reinforcement Learning (RL)-Pipeline für Schulung, Auswertung und Datenerfassung.

Um diesen Code live auszuführen, klicken Sie oben auf den Link "In Google Colab ausführen".

Einrichten

Wenn Sie die folgenden Abhängigkeiten nicht installiert haben, führen Sie Folgendes aus:

sudo apt-get update
sudo apt-get install -y xvfb ffmpeg
pip install 'imageio==2.4.0'
pip install pyvirtualdisplay
pip install tf-agents
from __future__ import absolute_import, division, print_function

import base64
import imageio
import IPython
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import PIL.Image
import pyvirtualdisplay

import tensorflow as tf

from tf_agents.agents.dqn import dqn_agent
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 sequential
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.specs import tensor_spec
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()
tf.version.VERSION
'2.5.0'

Hyperparameter

num_iterations = 20000 # @param {type:"integer"}

initial_collect_steps = 100  # @param {type:"integer"} 
collect_steps_per_iteration = 1  # @param {type:"integer"}
replay_buffer_max_length = 100000  # @param {type:"integer"}

batch_size = 64  # @param {type:"integer"}
learning_rate = 1e-3  # @param {type:"number"}
log_interval = 200  # @param {type:"integer"}

num_eval_episodes = 10  # @param {type:"integer"}
eval_interval = 1000  # @param {type:"integer"}

Umgebung

Beim Reinforcement Learning (RL) repräsentiert eine Umgebung die zu lösende Aufgabe oder das Problem. Standardumgebungen können in TF-Agents mithilfe von tf_agents.environments Suiten erstellt werden. TF-Agents bietet Suiten zum Laden von Umgebungen aus Quellen wie OpenAI Gym, Atari und DM Control.

Laden Sie die CartPole-Umgebung aus der OpenAI Gym-Suite.

env_name = 'CartPole-v0'
env = suite_gym.load(env_name)

Sie können diese Umgebung rendern, um zu sehen, wie sie aussieht. An einem Wagen ist eine freischwingende Stange befestigt. Das Ziel ist es, den Wagen nach rechts oder links zu bewegen, damit die Stange nach oben zeigt.

env.reset()
PIL.Image.fromarray(env.render())

png

Die Methode environment.step führt eine action in der Umgebung aus und gibt ein TimeStep Tupel zurück, das die nächste Beobachtung der Umgebung und die Belohnung für die Aktion enthält.

Die Methode time_step_spec() gibt die Spezifikation für das TimeStep Tupel zurück. Das observation zeigt die Form der Beobachtungen, die Datentypen und die zulässigen Wertebereiche an. Das reward zeigt dieselben Details für die Belohnung an.

print('Observation Spec:')
print(env.time_step_spec().observation)
Observation Spec:
BoundedArraySpec(shape=(4,), dtype=dtype('float32'), name='observation', minimum=[-4.8000002e+00 -3.4028235e+38 -4.1887903e-01 -3.4028235e+38], maximum=[4.8000002e+00 3.4028235e+38 4.1887903e-01 3.4028235e+38])
print('Reward Spec:')
print(env.time_step_spec().reward)
Reward Spec:
ArraySpec(shape=(), dtype=dtype('float32'), name='reward')

Die Methode action_spec() gibt Form, Datentypen und zulässige Werte gültiger Aktionen zurück.

print('Action Spec:')
print(env.action_spec())
Action Spec:
BoundedArraySpec(shape=(), dtype=dtype('int64'), name='action', minimum=0, maximum=1)

In der Cartpole-Umgebung:

  • observation ist ein Array von 4 Floats:
    • die Position und Geschwindigkeit des Wagens
    • die Winkellage und Geschwindigkeit des Pols
  • reward ist ein skalarer Float-Wert
  • action ist eine skalare ganze Zahl mit nur zwei möglichen Werten:
    • 0 – „nach links bewegen“
    • 1 – „nach rechts bewegen“
time_step = env.reset()
print('Time step:')
print(time_step)

action = np.array(1, dtype=np.int32)

next_time_step = env.step(action)
print('Next time step:')
print(next_time_step)
Time step:
TimeStep(
{'discount': array(1., dtype=float32),
 'observation': array([-0.02291739, -0.04223812,  0.04325358,  0.03615353], dtype=float32),
 'reward': array(0., dtype=float32),
 'step_type': array(0, dtype=int32)})
Next time step:
TimeStep(
{'discount': array(1., dtype=float32),
 'observation': array([-0.02376215,  0.15223774,  0.04397665, -0.24257484], dtype=float32),
 'reward': array(1., dtype=float32),
 'step_type': array(1, dtype=int32)})

Normalerweise werden zwei Umgebungen instanziiert: eine für das Training und eine für die Evaluierung.

train_py_env = suite_gym.load(env_name)
eval_py_env = suite_gym.load(env_name)

Die Cartpole-Umgebung ist wie die meisten Umgebungen in reinem Python geschrieben. Dies wird mit dem TFPyEnvironment Wrapper in TensorFlow TFPyEnvironment .

Die API der ursprünglichen Umgebung verwendet Numpy-Arrays. Die TFPyEnvironment wandelt diese in Tensors um, um sie mit Tensorflow-Agenten und -Richtlinien kompatibel zu machen.

train_env = tf_py_environment.TFPyEnvironment(train_py_env)
eval_env = tf_py_environment.TFPyEnvironment(eval_py_env)

Agent

Der zur Lösung eines RL-Problems verwendete Algorithmus wird durch einen Agent repräsentiert. TF-Agents bietet Standardimplementierungen einer Vielzahl von Agents , darunter:

Der DQN-Agent kann in jeder Umgebung verwendet werden, die über einen diskreten Aktionsraum verfügt.

Das Herzstück eines DQN-Agenten ist ein QNetwork , ein neuronales Netzwerkmodell, das lernen kann, QValues (erwartete Renditen) für alle Aktionen QValues einer Beobachtung aus der Umgebung vorherzusagen.

Wir werden tf_agents.networks. um ein QNetwork zu erstellen. Das Netzwerk besteht aus einer Folge von tf.keras.layers.Dense Schichten, wobei die letzte Schicht 1 Ausgabe für jede mögliche Aktion hat.

fc_layer_params = (100, 50)
action_tensor_spec = tensor_spec.from_spec(env.action_spec())
num_actions = action_tensor_spec.maximum - action_tensor_spec.minimum + 1

# Define a helper function to create Dense layers configured with the right
# activation and kernel initializer.
def dense_layer(num_units):
  return tf.keras.layers.Dense(
      num_units,
      activation=tf.keras.activations.relu,
      kernel_initializer=tf.keras.initializers.VarianceScaling(
          scale=2.0, mode='fan_in', distribution='truncated_normal'))

# QNetwork consists of a sequence of Dense layers followed by a dense layer
# with `num_actions` units to generate one q_value per available action as
# it's output.
dense_layers = [dense_layer(num_units) for num_units in fc_layer_params]
q_values_layer = tf.keras.layers.Dense(
    num_actions,
    activation=None,
    kernel_initializer=tf.keras.initializers.RandomUniform(
        minval=-0.03, maxval=0.03),
    bias_initializer=tf.keras.initializers.Constant(-0.2))
q_net = sequential.Sequential(dense_layers + [q_values_layer])

Verwenden tf_agents.agents.dqn.dqn_agent nun tf_agents.agents.dqn.dqn_agent , um einen DqnAgent zu instanziieren. Zusätzlich zu time_step_spec , action_spec und QNetwork benötigt der Agentenkonstruktor auch einen Optimierer (in diesem Fall AdamOptimizer ), eine Verlustfunktion und einen ganzzahligen Schrittzähler.

optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)

train_step_counter = tf.Variable(0)

agent = dqn_agent.DqnAgent(
    train_env.time_step_spec(),
    train_env.action_spec(),
    q_network=q_net,
    optimizer=optimizer,
    td_errors_loss_fn=common.element_wise_squared_loss,
    train_step_counter=train_step_counter)

agent.initialize()

Richtlinien

Eine Richtlinie definiert die Art und Weise, wie ein Agent in einer Umgebung handelt. In der Regel besteht das Ziel des Reinforcement Learning darin, das zugrunde liegende Modell zu trainieren, bis die Richtlinie das gewünschte Ergebnis liefert.

In diesem Tutorial:

  • Das gewünschte Ergebnis besteht darin, die Stange aufrecht über dem Wagen im Gleichgewicht zu halten.
  • Die Richtlinie gibt für jede time_step Beobachtung eine Aktion (links oder rechts) time_step .

Agenten enthalten zwei Richtlinien:

  • agent.policy – Die Hauptrichtlinie, die für die Evaluierung und Bereitstellung verwendet wird.
  • agent.collect_policy — Eine zweite Richtlinie, die für die Datensammlung verwendet wird.
eval_policy = agent.policy
collect_policy = agent.collect_policy

Richtlinien können unabhängig von Agenten erstellt werden. Verwenden Sie beispielsweise tf_agents.policies.random_tf_policy , um eine Richtlinie zu erstellen, die zufällig eine Aktion für jeden time_step .

random_policy = random_tf_policy.RandomTFPolicy(train_env.time_step_spec(),
                                                train_env.action_spec())

Um eine Aktion von einer Richtlinie policy.action(time_step) , rufen Sie die Methode policy.action(time_step) . Der time_step enthält die Beobachtung aus der Umgebung. Diese Methode gibt einen PolicyStep , bei dem es sich um ein benanntes Tupel mit drei Komponenten handelt:

  • action — die auszuführende Aktion (in diesem Fall 0 oder 1 )
  • state – wird für zustandsbehaftete (d. h. RNN-basierte) Richtlinien verwendet
  • info — Hilfsdaten, z. B. Log-Wahrscheinlichkeiten von Aktionen
example_environment = tf_py_environment.TFPyEnvironment(
    suite_gym.load('CartPole-v0'))
time_step = example_environment.reset()
random_policy.action(time_step)
PolicyStep(action=<tf.Tensor: shape=(1,), dtype=int64, numpy=array([1])>, state=(), info=())

Metriken und Auswertung

Die am häufigsten verwendete Kennzahl zur Bewertung einer Richtlinie ist die durchschnittliche Rendite. Die Rendite ist die Summe der Belohnungen, die Sie erhalten, wenn Sie eine Police in einer Umgebung für eine Episode ausführen. Mehrere Episoden werden ausgeführt, wodurch eine durchschnittliche Rendite entsteht.

Die folgende Funktion berechnet die durchschnittliche Rendite einer Richtlinie unter Berücksichtigung der Richtlinie, der Umgebung und einer Anzahl von Episoden.

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]


# See also the metrics module for standard implementations of different metrics.
# https://github.com/tensorflow/agents/tree/master/tf_agents/metrics

Das Ausführen dieser Berechnung mit der random_policy zeigt eine random_policy Leistung in der Umgebung.

compute_avg_return(eval_env, random_policy, num_eval_episodes)
28.4

Wiedergabepuffer

Der Wiedergabepuffer verfolgt die von der Umgebung gesammelten Daten. Dieses Tutorial verwendet tf_agents.replay_buffers.tf_uniform_replay_buffer.TFUniformReplayBuffer , da es am häufigsten vorkommt.

Der Konstruktor benötigt die Spezifikationen für die zu sammelnden Daten. Dies ist vom Agenten mit der Methode collect_data_spec verfügbar. Außerdem werden die Batchgröße und die maximale Pufferlänge benötigt.

replay_buffer = tf_uniform_replay_buffer.TFUniformReplayBuffer(
    data_spec=agent.collect_data_spec,
    batch_size=train_env.batch_size,
    max_length=replay_buffer_max_length)

Für die meisten Agenten ist collect_data_spec ein benanntes Tupel namens Trajectory , das die Spezifikationen für Beobachtungen, Aktionen, Belohnungen und andere Elemente enthält.

agent.collect_data_spec
Trajectory(
{'action': BoundedTensorSpec(shape=(), dtype=tf.int64, name='action', minimum=array(0), maximum=array(1)),
 'discount': BoundedTensorSpec(shape=(), dtype=tf.float32, name='discount', minimum=array(0., dtype=float32), maximum=array(1., dtype=float32)),
 'next_step_type': TensorSpec(shape=(), dtype=tf.int32, name='step_type'),
 'observation': BoundedTensorSpec(shape=(4,), dtype=tf.float32, name='observation', minimum=array([-4.8000002e+00, -3.4028235e+38, -4.1887903e-01, -3.4028235e+38],
      dtype=float32), maximum=array([4.8000002e+00, 3.4028235e+38, 4.1887903e-01, 3.4028235e+38],
      dtype=float32)),
 'policy_info': (),
 'reward': TensorSpec(shape=(), dtype=tf.float32, name='reward'),
 'step_type': TensorSpec(shape=(), dtype=tf.int32, name='step_type')})
agent.collect_data_spec._fields
('step_type',
 'observation',
 'action',
 'policy_info',
 'next_step_type',
 'reward',
 'discount')

Datensammlung

Führen Sie nun die Zufallsrichtlinie in der Umgebung für einige Schritte aus und zeichnen Sie die Daten im Wiedergabepuffer auf.

def collect_step(environment, policy, buffer):
  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
  buffer.add_batch(traj)

def collect_data(env, policy, buffer, steps):
  for _ in range(steps):
    collect_step(env, policy, buffer)

collect_data(train_env, random_policy, replay_buffer, initial_collect_steps)

# This loop is so common in RL, that we provide standard implementations. 
# For more details see tutorial 4 or the drivers module.
# https://github.com/tensorflow/agents/blob/master/docs/tutorials/4_drivers_tutorial.ipynb 
# https://www.tensorflow.org/agents/api_docs/python/tf_agents/drivers

Der Wiedergabepuffer ist jetzt eine Sammlung von Trajektorien.

# For the curious:
# Uncomment to peel one of these off and inspect it.
# iter(replay_buffer.as_dataset()).next()

Der Agent benötigt Zugriff auf den Wiedergabepuffer. Dies wird durch Erstellen einer iterierbarentf.data.Dataset Pipeline bereitgestellt, die dem Agenten Datentf.data.Dataset .

Jede Zeile des Wiedergabepuffers speichert nur einen einzelnen Beobachtungsschritt. Da der DQN-Agent jedoch sowohl die aktuelle als auch die nächste Beobachtung benötigt, um den Verlust zu berechnen, tastet die Dataset-Pipeline zwei benachbarte Zeilen für jedes Element im Batch ab ( num_steps=2 ).

Dieser Datensatz wird auch durch parallele Aufrufe und Vorabrufen von Daten optimiert.

# Dataset generates trajectories with shape [Bx2x...]
dataset = replay_buffer.as_dataset(
    num_parallel_calls=3, 
    sample_batch_size=batch_size, 
    num_steps=2).prefetch(3)


dataset
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.
<PrefetchDataset shapes: (Trajectory(
{action: (64, 2),
 discount: (64, 2),
 next_step_type: (64, 2),
 observation: (64, 2, 4),
 policy_info: (),
 reward: (64, 2),
 step_type: (64, 2)}), BufferInfo(ids=(64, 2), probabilities=(64,))), types: (Trajectory(
{action: tf.int64,
 discount: tf.float32,
 next_step_type: tf.int32,
 observation: tf.float32,
 policy_info: (),
 reward: tf.float32,
 step_type: tf.int32}), BufferInfo(ids=tf.int64, probabilities=tf.float32))>
iterator = iter(dataset)
print(iterator)
<tensorflow.python.data.ops.iterator_ops.OwnedIterator object at 0x7f480466f5d0>
# For the curious:
# Uncomment to see what the dataset iterator is feeding to the agent.
# Compare this representation of replay data 
# to the collection of individual trajectories shown earlier.

# iterator.next()

Schulung des Agenten

Während der Trainingsschleife müssen zwei Dinge passieren:

  • Daten aus der Umgebung sammeln
  • Verwenden Sie diese Daten, um die neuronalen Netze des Agenten zu trainieren.

In diesem Beispiel wird die Richtlinie auch regelmäßig ausgewertet und der aktuelle Score gedruckt.

Die Ausführung der folgenden Schritte dauert ca. 5 Minuten.

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.
  collect_data(train_env, agent.collect_policy, replay_buffer, collect_steps_per_iteration)

  # Sample a batch of data from the buffer and update the agent's network.
  experience, unused_info = next(iterator)
  train_loss = agent.train(experience).loss

  step = agent.train_step_counter.numpy()

  if step % log_interval == 0:
    print('step = {0}: loss = {1}'.format(step, train_loss))

  if step % eval_interval == 0:
    avg_return = compute_avg_return(eval_env, agent.policy, num_eval_episodes)
    print('step = {0}: Average Return = {1}'.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 = 18.56928825378418
step = 400: loss = 5.047736167907715
step = 600: loss = 14.25174331665039
step = 800: loss = 24.014192581176758
step = 1000: loss = 18.762466430664062
step = 1000: Average Return = 154.1999969482422
step = 1200: loss = 48.24091339111328
step = 1400: loss = 32.6214599609375
step = 1600: loss = 47.680694580078125
step = 1800: loss = 242.03060913085938
step = 2000: loss = 73.53008270263672
step = 2000: Average Return = 200.0
step = 2200: loss = 53.16136169433594
step = 2400: loss = 373.9162902832031
step = 2600: loss = 39.21461486816406
step = 2800: loss = 105.97955322265625
step = 3000: loss = 119.51268768310547
step = 3000: Average Return = 200.0
step = 3200: loss = 226.07618713378906
step = 3400: loss = 442.111572265625
step = 3600: loss = 437.02545166015625
step = 3800: loss = 662.8380737304688
step = 4000: loss = 782.982421875
step = 4000: Average Return = 200.0
step = 4200: loss = 121945.578125
step = 4400: loss = 2674.33154296875
step = 4600: loss = 2334.872802734375
step = 4800: loss = 2527.200927734375
step = 5000: loss = 8297.3955078125
step = 5000: Average Return = 200.0
step = 5200: loss = 8597.1923828125
step = 5400: loss = 7340.04443359375
step = 5600: loss = 3453.21728515625
step = 5800: loss = 27120.724609375
step = 6000: loss = 48760.671875
step = 6000: Average Return = 200.0
step = 6200: loss = 38986.421875
step = 6400: loss = 48238.234375
step = 6600: loss = 57711.22265625
step = 6800: loss = 274270.9375
step = 7000: loss = 63824.61328125
step = 7000: Average Return = 200.0
step = 7200: loss = 119148.859375
step = 7400: loss = 159678.6875
step = 7600: loss = 141013.96875
step = 7800: loss = 596496.9375
step = 8000: loss = 563607.125
step = 8000: Average Return = 200.0
step = 8200: loss = 7630604.0
step = 8400: loss = 13285580.0
step = 8600: loss = 333170048.0
step = 8800: loss = 23120384.0
step = 9000: loss = 369857056.0
step = 9000: Average Return = 200.0
step = 9200: loss = 17108284.0
step = 9400: loss = 49773056.0
step = 9600: loss = 21419348.0
step = 9800: loss = 148333248.0
step = 10000: loss = 67406928.0
step = 10000: Average Return = 77.0999984741211
step = 10200: loss = 16730348.0
step = 10400: loss = 19317756.0
step = 10600: loss = 12585502.0
step = 10800: loss = 15987130.0
step = 11000: loss = 32655918.0
step = 11000: Average Return = 200.0
step = 11200: loss = 11686570.0
step = 11400: loss = 15297463.0
step = 11600: loss = 15890760.0
step = 11800: loss = 17948140.0
step = 12000: loss = 7198852.5
step = 12000: Average Return = 200.0
step = 12200: loss = 12537673.0
step = 12400: loss = 11662791.0
step = 12600: loss = 157308304.0
step = 12800: loss = 9338672.0
step = 13000: loss = 7486102.0
step = 13000: Average Return = 200.0
step = 13200: loss = 7827698.5
step = 13400: loss = 7565884.0
step = 13600: loss = 12146330.0
step = 13800: loss = 8902687.0
step = 14000: loss = 12659248.0
step = 14000: Average Return = 200.0
step = 14200: loss = 9578409.0
step = 14400: loss = 13338937.0
step = 14600: loss = 12442834.0
step = 14800: loss = 8154804.5
step = 15000: loss = 14968015.0
step = 15000: Average Return = 200.0
step = 15200: loss = 6897091.0
step = 15400: loss = 11543962.0
step = 15600: loss = 8033916.5
step = 15800: loss = 16707812.0
step = 16000: loss = 3942055680.0
step = 16000: Average Return = 200.0
step = 16200: loss = 9505360.0
step = 16400: loss = 5509431.5
step = 16600: loss = 9405398.0
step = 16800: loss = 8809309.0
step = 17000: loss = 10677678.0
step = 17000: Average Return = 200.0
step = 17200: loss = 10017460.0
step = 17400: loss = 8878522.0
step = 17600: loss = 9307826.0
step = 17800: loss = 8975850.0
step = 18000: loss = 11676451.0
step = 18000: Average Return = 200.0
step = 18200: loss = 355074080.0
step = 18400: loss = 22255044.0
step = 18600: loss = 16955560.0
step = 18800: loss = 12466311.0
step = 19000: loss = 17620040.0
step = 19000: Average Return = 200.0
step = 19200: loss = 6484491.5
step = 19400: loss = 14639623.0
step = 19600: loss = 11706258.0
step = 19800: loss = 19145572.0
step = 20000: loss = 13256708.0
step = 20000: Average Return = 200.0

Visualisierung

Grundstücke

Verwenden Sie matplotlib.pyplot , um matplotlib.pyplot , wie sich die Richtlinie während des Trainings verbessert hat.

Eine Iteration von Cartpole-v0 besteht aus 200 Cartpole-v0 . Die Umgebung gibt eine Belohnung von +1 für jeden Schritt, den die Stange aufrecht hält, sodass die maximale Rendite für eine Episode 200 beträgt. Die Diagramme zeigen, dass die Rendite jedes Mal, wenn sie während des Trainings bewertet wird, in Richtung dieses Maximums ansteigt. (Es kann ein wenig instabil sein und nicht jedes Mal monoton zunehmen.)

iterations = range(0, num_iterations + 1, eval_interval)
plt.plot(iterations, returns)
plt.ylabel('Average Return')
plt.xlabel('Iterations')
plt.ylim(top=250)
(-0.1300004005432136, 250.0)

png

Videos

Diagramme sind schön. Spannender ist es jedoch zu sehen, wie ein Agent tatsächlich eine Aufgabe in einer Umgebung ausführt.

Erstellen Sie zunächst eine Funktion zum Einbetten von Videos in das Notebook.

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)

Durchlaufen Sie nun mit dem Agenten einige Episoden des Cartpole-Spiels. Die zugrunde liegende Python-Umgebung (die "innerhalb" des TensorFlow-Umgebungswrappers) stellt eine render() Methode bereit, die ein Bild des Umgebungszustands ausgibt. Diese können zu einem Video zusammengefasst werden.

def create_policy_eval_video(policy, filename, num_episodes=5, fps=30):
  filename = filename + ".mp4"
  with imageio.get_writer(filename, fps=fps) 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 = policy.action(time_step)
        time_step = eval_env.step(action_step.action)
        video.append_data(eval_py_env.render())
  return embed_mp4(filename)




create_policy_eval_video(agent.policy, "trained-agent")
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.

Vergleichen Sie zum Spaß den trainierten Agenten (oben) mit einem zufällig bewegten Agenten. (Es geht nicht so gut.)

create_policy_eval_video(random_policy, "random-agent")
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.