Kurs
Erste Schritte mit TorchRL für Deep Reinforcement Learning
Reinforcement Learning (RL) wird zur Lösung vieler komplexer Probleme eingesetzt, vom Training selbstfahrender Autos bis zum Training großer Sprachmodelle (LLMs), die menschenähnliche Antworten geben.
RL-Agenten werden mit Hilfe von Reinforcement Learning from Human Feedback (RLHF) darauf trainiert, auf menschliches Feedback zu reagieren. Obwohl Python-basierte Frameworks wie Keras und Tensorflow in Deep-Learning-Anwendungen von Unternehmen eingesetzt werden, basieren die meisten neuen Projekte inzwischen auf PyTorch und PyTorch Lightning.
TorchRL ist eine Open-Source-Bibliothek zur Erstellung von RL-Lösungen mit PyTorch. In diesem Tutorial zeige ich dir, wie du TorchRL einrichtest, die zugrundeliegenden Komponenten verstehst und damit einen einfachen RL-Agenten baust. Wir werden auch die Verwendung von TorchRL besprechen, um vorgefertigte Versionen von RL-Algorithmen wie Proximal Policy Optimization (PPO) zu implementieren. Zum Schluss werden wir die Grundprinzipien der Protokollierung und Überwachung von RL-Agenten behandeln.
Was ist TorchRL und warum sollte man es benutzen?
RL-Algorithmen sind oft komplex. Du musst den/die Agenten erstellen, die Renditen und Verluste berechnen, die Forward- und Backward-Passes definieren und die Leistung des Agenten bewerten.
TorchRL packt viele häufig verwendete RL-Funktionen in Module, auf die du direkt zugreifen kannst. Das macht die Implementierung und das Experimentieren mit verschiedenen Algorithmen zur Lösung praktischer Probleme einfacher. Es macht es auch einfacher, neue Algorithmen zu entwickeln, weil Forscher/innen Zugang zum restlichen RL-Ökosystem haben, ohne es selbst entwickeln zu müssen.
TorchRL kommt mit vielen vorgefertigten Modulen, die die RL-Entwicklung effizienter machen. Zum Beispiel:
- Umgebungen: TorchRL bietet eine standardisierte API, um RL-Umgebungen aus verschiedenen Quellen zu importieren und zu nutzen, darunterGymnasium, Jumanji, RoboHive undre. In vielen Fällen ist es notwendig, den Output der Umgebung an die spezifischen Ausbildungsbedürfnisse anzupassen. TorchRL enthält Module für verschiedene Umwelttransformationen, die einen einzigen Funktionsaufruf mit den gewünschten Parametern verwenden.
- Datensammler und Replay-Puffer: Bei vielen RL-Trainingsalgorithmen werden Daten über die Interaktionen des Agenten mit der Umwelt gesammelt - die Aktion des Agenten, die Belohnung, die er erhalten hat, und der nächste Zustand, in dem er sich befindet. TorchRL enthält Pakete mit den Datenstrukturen, um diese Informationen zu sammeln und abzufragen.
- Objektive Funktionen: Die Kernmethodik eines RL-Algorithmus ist in seiner Zielfunktion implementiert. TorchRL packt gängige RL-Algorithmen wie DQN (Deep Q Networks), A2C (Advantage Actor-Critic), PPO und viele mehr in vorgefertigte Module, die du direkt aufrufen und zum Trainieren des Agenten verwenden kannst.
Mit den oben genannten Funktionen hat sich TorchRL als nützlich erwiesen, um den Aufbau von RL-Lösungen für verschiedene Anwendungsfälle zu rationalisieren und zu vereinfachen:
- Robotik: Der Roboter muss darauf trainiert werden, sich in einer komplexen Umgebung zurechtzufinden. Er wird bestraft, wenn er stolpert oder anderweitig nicht navigieren kann. Mithilfe von RL-Trainingsmethoden lernt es die richtigen Aktionen, um erfolgreich durch eine Umgebung wie eine unebene natürliche Oberfläche zu navigieren.
- Spiel-KI: Computergestützte Spieler/innen in Video- und Konsolenspielen müssen ihre Spielzüge als Reaktion auf die Aktionen der menschlichen Spieler/innen entwickeln und improvisieren. RL, mit Belohnungen und Strafen, wird verwendet, um diese Spieler zu trainieren, die richtigen Züge zu wählen, um gegen den Menschen zu spielen.
- Autonome Systeme: Selbstfahrende Autos müssen sich selbstständig in einer komplexen Umgebung (wie dem Straßenverkehr) zurechtfinden und das Ziel unfallfrei erreichen. RL wird verwendet, um autonome Systeme so zu trainieren, dass sie das Verhalten eines menschlichen Fahrers unter einer Vielzahl von realen Bedingungen nachahmen.
KI-Anwendungen entwickeln
Einrichten von TorchRL
In diesem Abschnitt zeige ich dir, wie du TorchRL installierst und loslegst.
Voraussetzungen
Bevor du TorchRL installieren und benutzen kannst, benötigst du einige Softwarepakete, die von anderen abhängig sind:
- PyTorch: TorchRL basiert auf PyTorch, du brauchst es also als Voraussetzung.
- Gymnasium: Unterbrauchst du das Paket Gymnasium, um RL-Umgebungen zu importieren. Ab Januar 2025 ist die neueste Version von Gymnasium nicht mehr mit TorchRL kompatibel, wie auf dieser Git-Diskussionsseite erklärt wird. Installiere also die ältere Version
0.29.1
. - PyGame: Es ist ein Python-Paket für Videospiele. TorchRL braucht es, um spielähnliche RL-Umgebungen zu simulieren, wie CartPole.
- TensorDict: Die Verwendung einer wörterbuchähnlichen Datenstruktur zur Speicherung der Ein- und Ausgänge neuronaler Netze macht die Arbeit mit Tensoren in TorchRL bequem. TensorDict bietet einen Tensor-Container, der Tensoren als Schlüssel-Wert-Paare speichert.
Installiere die vorausgesetzten Pakete:
!pip install torch tensordict gymnasium==0.29.1 pygame
Installing TorchRL
Installiere TorchRL mit pip
. Ich empfehle dringend, diese Pakete in einer Conda-Umgebung zu installieren, wenn du auf einem PC oder Server arbeitest.
!pip install torchrl
Überprüfen der Installation
Teste nach der Installation, ob TorchRL erfolgreich installiert wurde. Versuche, torchrl
in einer Python-Shell (oder einem Notebook) zu importieren. Mit der Methode check_env_specs()
kannst du überprüfen, ob eine Standardumgebung (z.B. CartPole) mit den Spezifikationen von torchrl
übereinstimmt:
import torchrl
from torchrl.envs import GymEnv
from torchrl.envs.utils import check_env_specs
check_env_specs(GymEnv("CartPole-v1"))
Die Ausgabe sollte anzeigen, dass die Umgebung erfolgreich erstellt wurde und dass sie mit TorchRL funktioniert.
[torchrl][INFO] check_env_specs succeeded!
Die wichtigsten Komponenten von TorchRL
Bevor du deinen ersten RL-Agenten erstellst, lass uns einen Blick auf die Kernbausteine von TorchRL werfen.
Umgebungen
TorchRL bietet eine einheitliche API für die Schnittstelle zu verschiedenen Umgebungen. Dies geschieht, indem einzelne umgebungsspezifische Funktionalitäten in einen Standardsatz von Wrapper-Klassen und -Funktionen verpackt werden. Du übergibst dem Wrapper die entsprechenden Parameter und er ordnet deinen Befehl intern dem entsprechenden Funktionsaufruf in der jeweiligen Umgebung zu. Im Besonderen:
- TorchRL wandelt Umgebungszustände (Beobachtungen), Aktionen und Belohnungen in PyTorch-Tensorobjekte um, die direkt von den Modulen verwendet werden können, die RL-Algorithmen implementieren.
- Es ermöglicht die Anwendung von Vor- und Nachbearbeitungsschritten, z. B. zur Normalisierung und Skalierung von Eingangstensoren oder zur Darstellung von Ausgangstensoren in einem bestimmten Format.
Um zum Beispiel eine Umgebung von Gymnasium zu erstellen, verwende das Modul GymEnv
:
env = GymEnv("CartPole-v1")
Transformiert
Es ist üblich, die Standardumgebung mit zusätzlichen Funktionen und Transformationen zu erweitern, die du sonst selbst implementieren müsstest. Du kannst zum Beispiel ein Schrittzähler-Modul zur Umgebung hinzufügen, anstatt den Zähler selbst zu programmieren. Der Schrittzähler hält die Anzahl der Schritte in jeder Folge fest. Das Modul transformedEnv
hilft dabei:
from torchrl.envs import GymEnv, StepCounter, TransformedEnv
env = TransformedEnv(GymEnv("CartPole-v1"), StepCounter())
Auch die Normalisierung von Tensoren vor der Bearbeitung ist ein gängiger Schritt der Vorverarbeitung. Eine Normalisierungstransformation, die das Modul ObservationNorm
verwendet, normalisiert die Tensoren. In der Dokumentation der Funktion TransformedEnv werden verschiedene Arten von Transformationen beschrieben.
Du kannst auch mehrere Transformationen mit dem Parameter compose()
kombinieren:
base_env = GymEnv('CartPole-v1', device=device)
env = TransformedEnv(
base_env,
Compose(
ObservationNorm(in_keys=["observation"]),
StepCounter()
)
)
Agenten und Politik
Im RL entscheidet der Agent seine Handlungen anhand der Politik und des beobachteten Zustands der Umgebung. Das Ziel des Agenten ist es, die kumulierten Belohnungen aus der Umwelt zu maximieren. Er wird belohnt, wenn er die richtige Aktion wählt (z. B. an einer roten Ampel anhalten).
Bei einem selbstfahrenden Auto zum Beispiel fährt der Agent das Auto. Seine Entscheidungen (z. B. das Auto in eine bestimmte Richtung zu lenken) basieren auf seinen Beobachtungen der Umgebung (z. B. Verkehr, Position des Autos usw.) und seiner Strategie (z. B. Fußgängern und anderen Hindernissen ausweichen, an roten Ampeln anhalten usw.).
Die einfachste Strategie ist, eine Aktion nach dem Zufallsprinzip zu wählen. Der Akteur wählt zufällig eine der Aktionen aus dem Raum der möglichen Aktionen aus. Manchmal wird eine Zufallsstrategie verwendet, um einen ersten Datensatz von Interaktionen zu erzeugen, bevor das Modell trainiert wird.
Verwende das Modul RandomPolicy
, um eine Zufallsrichtlinie zu erstellen. Diese Zufallsrichtlinie akzeptiert einen action_spec
Parameter, der den Aktionsraum angibt. In dem folgenden Beispiel besteht der Aktionsraum aus (kontinuierlichen) Zahlen zwischen -1 und +1. Die Zufallsstrategie wählt also eine Aktion, die durch eine Zufallszahl zwischen -1 und +1 dargestellt wird.
import torchrl
import torch
from tensordict import TensorDict
from torchrl.data.tensor_specs import Bounded
action_spec = Bounded(-torch.ones(1), torch.ones(1))
actor = torchrl.envs.utils.RandomPolicy(action_spec=action_spec)
td = actor(TensorDict({}, batch_size=[]))
print(td.get("action"))
Die Ausgabe sollte ein Tensor sein, wie unten gezeigt:
tensor([0.9258])
Prüfe, ob die Richtlinie tatsächlich zufällig ist, indem du den Akteur erneut ausführst:
td = actor(TensorDict({}, batch_size=[]))
print(td.get("action"))
Es sollte einen anderen Zufallstensor ausgeben.
Wenn du eine Einführung in RL-Konzepte brauchst, schau dir den Lernpfad Reinforcement Learning in Python auf dem DataCamp an!
Aufbau deines ersten RL-Agenten mit TorchRL
In diesem Abschnitt zeige ich dir, wie du einen einfachen Reinforcement Learning Agent mit TorchRL implementierst.
Bevor du beginnst, importiere die erforderlichen Softwarepakete in Python:
time
um die Zeit zu messen, die für die Ausbildung des Agenten benötigt wird.GymEnv
,StepCounter
, undTransformedEnv
für die Arbeit in der Turnhalle.MLP
um ein einfaches MLP (Multi-Layer Perceptron) neuronales Netzwerk zu erstellen.EGreedyModule
das Gleichgewicht zwischen der Erkundung der Umwelt und der Ausnutzung der besten Politik.QValueModule
undDQNLoss
, um den Deep-Q-Learning-Algorithmus zu implementieren.SoftUpdate
um das neuronale Netz zu aktualisieren.SyncDataCollector
um Daten über die Interaktionen des Agenten zu sammeln.ReplayBuffer
um die Daten aus den Interaktionen des Agenten zu speichern.Adam
für Backpropagation.matplotlib
um den Trainingsfortschritt visuell darzustellen.torchrl_logger
um die Trainingseinheit zu protokollieren.
import time
import matplotlib.pyplot as plt
from torchrl.envs import GymEnv, StepCounter, TransformedEnv
from tensordict.nn import TensorDictModule as TensorDict, TensorDictSequential as Seq
from torchrl.modules import EGreedyModule, MLP, QValueModule
from torchrl.objectives import DQNLoss, SoftUpdate
from torchrl.collectors import SyncDataCollector
from torchrl.data import LazyTensorStorage, ReplayBuffer
from torch.optim import Adam
from torchrl._utils import logger as torchrl_logger
Schritt 1: Definiere die Umgebung
In diesem Beispiel lösen wir die CartPole-Umgebung. Importiere diese Umgebung von Gymnasium zusammen mit einem Schrittzähler, um die Anzahl der Trainingsschritte zu verfolgen:
env = TransformedEnv(GymEnv("CartPole-v1"), StepCounter())
Setze die Python- und RL-Umgebungen ein, um in allen Trainingseinheiten ähnliche Ergebnisse zu erzielen.
torch.manual_seed(0)
env = TransformedEnv(GymEnv("CartPole-v1"), StepCounter())
env.set_seed(0)
Lege die Parameter und Hyperparameter für das Training fest:
INIT_RAND_STEPS
: Die Anzahl der Schritte, bei denen der Agent nach dem Zufallsprinzip handelt, bevor er die Richtlinie anwendet. Diese ersten Schritte dienen dazu, erste Daten zu sammeln, um mit dem Training der Strategie zu beginnen.FRAMES_PER_BATCH
: Die Anzahl der Datenpunkte (einer für jede Interaktion oder jeden Zeitschritt) in einem Trainingsstapel.OPTIM_STEPS
: Die Anzahl der Schritte, für die die Verluste akkumuliert werden sollen, bevor ein Durchgang des Rückwärtsdurchlaufs ausgeführt wird.EPS_0
: Der Anfangswert von epsilon, dem Erkundungskoeffizienten.BUFFER_LEN
: Die Größe des Puffers für die Wiedergabe.ALPHA
: Die Lernrate.TARGET_UPDATE_EPS
: Der Abklingfaktor für die Aktualisierung des Zielnetzes using das Soft-Update-Modul.REPLAY_BUFFER_SAMPLE
: Die Größe der Zufallsstichprobe, die in jeder Trainingsiteration aus dem Wiederholungspuffer gezogen wird. Der Wiedergabepuffer speichert die Ergebnisse der Interaktionen des Agenten mit der Umwelt in jedem Zeitschritt.LOG_EVERY
: Die Anzahl der Schritte, nach denen der Trainingsfortschritt ausgedruckt werden soll.MLP_SIZE
: Die Größe des neuronalen Netzes.
INIT_RAND_STEPS = 5000
FRAMES_PER_BATCH = 100
OPTIM_STEPS = 10
EPS_0 = 0.5
BUFFER_LEN = 100_000
ALPHA = 0.05
TARGET_UPDATE_EPS = 0.95
REPLAY_BUFFER_SAMPLE = 128
LOG_EVERY = 1000
MLP_SIZE = 64
Schritt 2: Die Richtlinie erstellen
Definiere ein einfaches neuronales Netz, um die Richtlinie umzusetzen:
- Definiere das MLP (neuronales Netz). Wenn eine Beobachtung vorliegt, gibt das MLP den Aktionswert aus und übernimmt damit die Aufgabe der Q-Funktion.
- Definiere ein Tensor-Wörterbuch mit Hilfe des Moduls
TensorDict
für die oben genannte MLP. Dieses Wörterbuch ordnet die Zustandsbeobachtungen der Umgebung (Wörterbuchschlüssel) den Aktionswahrscheinlichkeitswerten (Wörterbuchwerte) zu, die diesem Zustand entsprechen. - Verwende das QValueModule, um die Q-Funktion zu implizierenementieren. Gibt einen Tensor mit Aktionswerten an und gibt die Aktion zurück, die dem höchsten Aktionswert entspricht. Sie setzt die gierige (Ausbeutungs-)Strategie um.
- Kombiniere (mit demTensorDictSequential-Modul) das Tensor-Wörterbuch der MLP und die
QValueModule
, um die Richtlinie zu definieren .
value_mlp = MLP(out_features=env.action_spec.shape[-1], num_cells=[MLP_SIZE, MLP_SIZE])
value_net = TensorDict(value_mlp, in_keys=["observation"], out_keys=["action_value"])
policy = Seq(value_net, QValueModule(spec=env.action_spec))
- Definiere die Erkundungsfunktion mit dem EGreedyModul - sie benötigt als Eingabe den Aktionsraum der Umgebung, die Länge des Wiedergabepuffers und den Erkundungskoeffizienten Epsilon. Verkette (mit dem TensorDictSequential Modul) diese Explorationsfunktion mit der oben definierten Richtlinie, um die endgültige Richtlinie zu erhalten:
exploration_module = EGreedyModule(
env.action_spec, annealing_num_steps=BUFFER_LEN, eps_init=EPS_0
)
policy_explore = Seq(policy, exploration_module)
Schritt 3: Den Agenten ausbilden
Der erste Schritt beim Training des Agenten ist das Sammeln von Daten aus den Interaktionen des Agenten mit seiner Umgebung. Verwende den SyncDataCollector, um einen Collector zu erstellen, der die Richtlinie ausführt und die Ergebnisse der Interaktionen des Agenten sammelt:
collector = SyncDataCollector(
env,
policy_explore,
frames_per_batch=FRAMES_PER_BATCH,
total_frames=-1,
init_random_frames=INIT_RAND_STEPS,
)
Erstelle einen Wiedergabepuffer, um die Ergebnisse der Interaktionen zu speichern:
rb = ReplayBuffer(storage=LazyTensorStorage(BUFFER_LEN))
Du musst auch trainingsspezifische Module deklarieren, z. B. die Verlustfunktion (zur Verwendung der DQN-basierten Verlustberechnung), den Optimierer (den traditionellen Adam-Algorithmus) und die Updater-Funktionen (zur Aktualisierung des neuronalen Netzes). Sie basieren alle auf vordefinierten TorchRL-Modulen:
loss = DQNLoss(value_network=policy, action_space=env.action_spec, delay_value=True)
optim = Adam(loss.parameters(), lr=ALPHA)
updater = SoftUpdate(loss, eps=TARGET_UPDATE_EPS)
Initialisiere die Zähler, um die Gesamtzahl der Schritte und Episoden, die erfolgreichen Schritte pro Episode und die Ausführungszeit zu erfassen:
total_count = 0
total_episodes = 0
t0 = time.time()
success_steps = []
Die Trainingsfunktion besteht aus 2 for
Schleifen :
- Die oberste Schleife führt die Richtlinie aus und fügt die Ergebnisse der Interaktionen des Agenten an den Wiedergabepuffer an.
- Die innere Schleife teilt die Trainingsproben in Stapel auf. Es verarbeitet jede Charge wie folgt:
- Wähle eine zufällige Probe aus dem Wiedergabepuffer.
- Berechne die Verluste mithilfe der Verlustfunktion.
- Führe den Optimierer und den Updater aus.
- Aktualisiere die Zähler.
Bei jedem Schritt werden vorgefertigte TorchRL-Module aufgerufen, ohne dass du etwas neu programmieren musst. Der folgende Code zeigt, wie du diese Schritte umsetzt:
for i, data in enumerate(collector):
rb.extend(data)
max_length = rb[:]["next", "step_count"].max()
if len(rb) > INIT_RAND_STEPS:
for _ in range(OPTIM_STEPS):
sample = rb.sample(REPLAY_BUFFER_SAMPLE)
loss_vals = loss(sample)
loss_vals["loss"].backward()
optim.step()
optim.zero_grad()
# Update exploration factor
exploration_module.step(data.numel())
# Update target params
updater.step()
total_count += data.numel()
total_episodes += data["next", "done"].sum()
success_steps.append(max_length)
Schritt 4: Beurteile den Agenten
Die Schleife im vorherigen Abschnitt trainiert die Richtlinie kontinuierlich. Wir müssen die Kriterien für die Leistungsbewertung festlegen und entscheiden, wann wir die Ausbildung als erfolgreich ansehen. Wir wollen auch den Fortschritt der Ausbildung ausgeben.
Wir drucken den Fortschritt des Trainings in regelmäßigen Abständen mit dem TorchRL-Logger aus:
if total_count > 0 and total_count % LOG_EVERY == 0:
torchrl_logger.info(f"Successful steps in the last episode: {max_length}, rb length {len(rb)}, Number of episodes: {total_episodes}")
Wir verwenden die maximale Anzahl von Schritten, die der Agent in der letzten Episode erreicht hat, um festzustellen, ob das Training erfolgreich ist. Die CartPole-v1-Umgebung begrenzt die maximale Anzahl der Schritte und die Gesamtbelohnung pro Episode auf 500. Es ist üblich, eine Politik als erfolgreich zu betrachten, wenn sie mehr als 475 Schritte erreicht:
if max_length > 475:
print("TRAINING COMPLETE")
break
Die beiden obigen Codeschnipsel sollten am Ende der Trainingsschleife (siehe oben) angehängt werden. Das folgende Snippet zeigt die Trainingsschleife mit dem Code zur Auswertung des Agenten:
for i, data in enumerate(collector):
# Write data in replay buffer
rb.extend(data)
max_length = rb[:]["next", "step_count"].max()
if len(rb) > INIT_RAND_STEPS:
for _ in range(OPTIM_STEPS):
sample = rb.sample(REPLAY_BUFFER_SAMPLE)
loss_vals = loss(sample)
loss_vals["loss"].backward()
optim.step()
optim.zero_grad()
# Update exploration factor
exploration_module.step(data.numel())
# Update target params
updater.step()
total_count += data.numel()
total_episodes += data["next", "done"].sum()
success_steps.append(max_length)
if total_count > 0 and total_count % LOG_EVERY == 0:
torchrl_logger.info(f"Successful steps in the last episode: {max_length}, rb length {len(rb)}, Number of episodes: {total_episodes}")
if max_length > 475:
print("TRAINING COMPLETE")
break
Drucke nach dem Training und der Auswertung die gesamte Trainingszeit aus und stelle den Trainingsfortschritt dar:
t1 = time.time()
torchrl_logger.info(
f"solved after {total_count} steps, {total_episodes} episodes and in {t1-t0}s."
)
def plot_steps():
plt.plot(success_steps)
plt.title('Successful steps over training episodes')
plt.xlabel('Training episodes')
plt.ylabel('Steps')
plt.show()
plot_steps()
Du kannst den kompletten Code zur Implementierung des DQN mit TorchRL in dieser DataLab-Arbeitsmappe finden und ausführen.
In diesem Abschnitt haben wir einen RL-Agenten gebaut und mit dem einfachen DQN-Algorithmus trainiert. Im nächsten Abschnitt untersuchen wir, wie man vorgefertigte TorchRL-Module verwendet, um einen komplexeren Algorithmus wie PPO zu implementieren.
Vorgefertigte Algorithmen in TorchRL erforschen
Wie in den vorherigen Abschnitten erwähnt, enthält TorchRL einige vorgefertigte Algorithmen. Schauen wir uns diese an und wie sie funktionieren.
Unterstützte Algorithmen
TorchRL enthält vorgefertigte Module für viele gängige Deep Reinforcement Learning-Algorithmen, wie z. B.:
- Tiefe Q-Netze (DQN)
- Tiefer deterministischer Politikgradient (DDPG)
- Weiche Schauspieler-Kritik (SAC)
- Randomized ensembled double Q-learning (REDQ)
- CrossQ
- Implizites Q-Lernen (IQL)
- Kontinuierliches Q-Learning (CQL)
- Generatives adversariales Nachahmungslernen (GAIL)
- Entscheidungstransformator (DT)
- Twin-delayed DDPG (TD3)
- Akteur-Vorteil-Kritiker (A2C)
- Proximale Politikoptimierung (PPO)
- REINFORCE
- und mehr
Das macht es effizient, mit verschiedenen Arten von Algorithmen zu experimentieren und die Leistung der einzelnen Algorithmen für die Lösung eines bestimmten Problems zu untersuchen.
Beispiel: PPO in TorchRL
Proximal Policy Optimization verwendet eine beschnittene Surrogat-Zielfunktion, um einen reibungslosen Trainingsprozess zu erreichen, der ein Gleichgewicht zwischen Exploration und Exploitation herstellt.
In diesem Abschnitt zeige ich dir, wie du das vorgefertigte PPO-Modul in TorchRL verwenden kannst. Ähnlich wie bei der früheren Implementierung importierst du die vorausgesetzten Module. Zusätzlich zu den Modulen (wie ReplayBuffer
, SyncDataCollector
, etc.), die für die vorherige Implementierung benötigt wurden, brauchst du für PPO ein paar zusätzliche Pakete:
- ProbabilisticActor, um eine Aktion stochastisch zu wählen. Die stochastische Wahl der Aktion (anstatt immer der Richtlinie zu folgen und die Belohnung zu maximieren) erleichtert die Erkundung der Umgebung und die Entdeckung optimalerer Pfade während des Trainings.
- OneHotCategorical, um eine One-Hot-Kodierung des Tensors zu erzeugen, der die log-Wahrscheinlichkeiten der Aktionen angibt.
- ValueOperator, um ein TorchRL-Modul zu erstellen, das auf dem neuronalen Netz basiert, das die Wertfunktion implementiert.
- GAE, um die verallgemeinerte Vorteilsschätzung umzusetzen. PPO verwendet eine Vorteilsfunktion als Stellvertreter für die Wertfunktion. Das Wertmodul (oben) ist ein Input für die GAE.
- ClipPPOLoss, um die geclippte Zielfunktion für die Umsetzung von PPO zu erstellen.
import torch
from torch import nn
from torchrl.envs import Compose, ObservationNorm, DoubleToFloat, StepCounter, TransformedEnv
from torchrl.envs.libs.gym import GymEnv
from torchrl.envs.utils import check_env_specs
from torchrl.modules import ProbabilisticActor, OneHotCategorical, ValueOperator
from torchrl.collectors import SyncDataCollector
from torchrl.data.replay_buffers import ReplayBuffer
from torchrl.data.replay_buffers.storages import LazyTensorStorage
from torchrl.data.replay_buffers.samplers import SamplerWithoutReplacement
from torchrl.objectives.value import GAE
from torchrl.objectives import ClipPPOLoss
from tensordict.nn import TensorDictModule
Deklariere die Parameter und Hyperparameter für das Training:
FRAMES_PER_BATCH
: Die Anzahl der Frames (Zeitschritte) in jedem Stapel von Daten, die aus den Interaktionen des Agenten mit der Umgebung resultieren.SUB_BATCH_SIZE
: Die Anzahl der Zeitschritte in jedem Teilstapel. Beim PPO-Training wird jede Partie in Teilpartien unterteilt.TOTAL_FRAMES
: Die Gesamtzahl der Zeitschritte, für die das Training durchgeführt werden soll.GAMMA
: Der Abzinsungsfaktor für die Diskontierung des Wertes der Belohnung aus zukünftigen Zeitschritten.CLIP_EPSILON
: Damit wird der Vertrauensbereich festgelegt, innerhalb dessen sich die Strategie in jeder nachfolgenden Trainingsiteration ändern kann. Dabei wird die aktualisierte Strategie so beschnitten, dass das Verhältnis zwischen den neuen und alten Wahrscheinlichkeiten innerhalb einer bestimmten Grenze liegt.ALPHA
: Die Lernrate.ENTROPY_EPS
: Dieser Hyperparameter steuert das Verhältnis von Erkundung und Ausbeutung.OPTIM_STEPS
: Die Anzahl, wie oft der Optimierer für jeden Teilstapel von Daten ausgeführt werden soll.LOG_EVERY
: Die Anzahl der Schritte, nach denen die Richtlinie ausgewertet und die Belohnungen gedruckt werden sollen.
FRAMES_PER_BATCH = 1024
TOTAL_FRAMES = 1048576
GAMMA = 0.99
LAMBDA = 0.95
CLIP_EPSILON = 0.2
ALPHA = 1e-4
ENTROPY_EPS = 5e-4
SUB_BATCH_SIZE = 64
OPTIM_STEPS = 8
LOG_EVERY = 16
Importiere die CartPole Basisumgebung von Gymnasium:
device="cpu"
base_env = GymEnv('CartPole-v1', device=device)
Deklariere die TorchRL-Umgebung, indem du die Basisumgebung importierst und Module zur Normalisierung der Beobachtungstensoren und zum Zählen der Schritte hinzufügst:
env = TransformedEnv(
base_env,
Compose(
ObservationNorm(in_keys=["observation"]),
DoubleToFloat(),
StepCounter()
)
)
Initialisiere die Umgebung und setze die Zufallszahlengeneratoren:
env.transform[0].init_stats(1024)
torch.manual_seed(0)
env.set_seed(0)
check_env_specs(env)
Erkläre den Akteur zu einem neuronalen Netz mit einer versteckten Schicht und 16 Gewichten. Es nimmt die Beobachtungen aus der Umwelt als Eingabe und gibt die Wahrscheinlichkeit jeder Handlung im Handlungsraum aus.
actor_net = nn.Sequential(
nn.Linear(env.observation_spec["observation"].shape[-1], 32, device=device),
nn.ReLU(),
nn.Linear(32, 32, device=device),
nn.ReLU(),
nn.Linear(32, env.action_spec.shape[-1], device=device),
nn.ReLU()
)
Erstelle ein Tensor-Wörterbuch (basierend auf dem obigen neuronalen Netz) mit Schlüsseln und Werten, die Zustände auf Handlungswahrscheinlichkeiten abbilden.
actor_module = TensorDictModule(actor_net, in_keys=["observation"], out_keys=["logits"])
Beim Training von PPO (und vielen anderen RL-Algorithmen) wählst du nicht immer die Aktion, die im nächsten Schritt zur höchsten Belohnung führt. Ein gewisses Maß an Zufälligkeit bei der Wahl der Aktion ermöglicht es dem Agenten, die Umgebung zu erkunden und bessere Wege zu entdecken, die langfristig zu höheren Renditen führen können. Erstelle einen probabilistischen Akteur, um dies zu tun:
actor = ProbabilisticActor(
module = actor_module,
spec = env.action_spec,
in_keys = ["logits"],
distribution_class = OneHotCategorical,
return_log_prob = True
)
Erstelle das Netz, um die Wertfunktion zu implementieren. Dieses Netz hat 16 Gewichte. Sie nimmt den Zustand der Umwelt (Beobachtung) als Eingabe und gibt den erwarteten Wert dieses Zustands aus.
value_net = nn.Sequential(
nn.Linear(env.observation_spec["observation"].shape[-1], 16, device=device),
nn.ReLU(),
nn.Linear(16, 1, device=device),
nn.ReLU()
)
Erstelle ein TorchRL-Modul, das die (oben implementierte) Wertfunktion mit dem ValueOperator()
verpackt. Dieses Modul ist mit anderen TorchRL-Komponenten verbunden.
value_module = ValueOperator(
module = value_net,
in_keys = ["observation"]
)
Erstelle den Wiedergabepuffer, um die Ergebnisse der Interaktionen des Agenten mit der Umgebung zu speichern:
replay_buffer = ReplayBuffer(
storage = LazyTensorStorage(max_size=FRAMES_PER_BATCH),
sampler = SamplerWithoutReplacement()
)
Erstelle einen Datensammler, um die Richtlinie in der Umgebung auszuführen und die Ergebnisse der Interaktionen des Agenten mit der Umgebung in jedem Zeitschritt (Frame) zu sammeln:
collector = SyncDataCollector(
env,
actor,
frames_per_batch = FRAMES_PER_BATCH,
total_frames = TOTAL_FRAMES,
split_trajs = True,
reset_at_each_iter = True,
device=device
)
Verwende das Modul GAE
, um die Vorteilsfunktion für PPO zu implementieren. Die Vorteilsfunktion basiert auf der Wertfunktion.
advantage_module = GAE(
gamma = GAMMA,
lmbda = GAMMA,
value_network = value_module,
average_gae = True
)
Verwende das integrierte Modul ClipPPOLoss
, um die Verlustfunktion nach dem PPO-Algorithmus zu implementieren:
loss_module = ClipPPOLoss(
actor_network = actor,
critic_network = value_module,
clip_epsilon = CLIP_EPSILON,
entropy_bonus = bool(ENTROPY_EPS),
entropy_coef = ENTROPY_EPS
)
Erkläre den Adam-Optimierer:
optim = torch.optim.Adam(loss_module.parameters(), lr=ALPHA)
Erstelle einen Planer, um die Lernrate im Laufe des Trainings schrittweise zu reduzieren:
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optim, TOTAL_FRAMES // FRAMES_PER_BATCH)
Baue die Trainingsschleife mit den oben erstellten Komponenten auf. Die Trainingsfunktion besteht aus drei for
Schleifen:
- Die äußerste Schleife durchläuft die Daten, die aus den Interaktionen des Agenten mit der Umwelt gesammelt wurden. Der Parameter
TOTAL_FRAMES
bestimmt, wie viele Zeitschritte der Agent laufen soll . - Die mittlere Schleife macht Folgendes:
- Er führt die innerste Schleife für eine feste Anzahl von Iterationen aus (normalerweise zwischen 5 und 10), die durch den Hyperparameter
OPTIM_STEPS
festgelegt wird. - Sie aktualisiert die Lernrate nach jeder Trainingsiteration.
- Sie berechnet auch den Wert der Vorteilsfunktion für jeden Zeitschritt.
- Überprüfe die Richtlinie regelmäßig und drucke die Belohnungen aus.
- In der innersten Schleife läuft die Trainingsschleife:
- Nimm einen Stapel Trainingsdaten aus dem Wiederholungspuffer.
- Berechne den Verlust mit dem Verlustmodul.
- Führe Backpropagation auf den Verlust aus.
- Verwende den Optimierer, um den Gradientenabstieg durchzuführen.
Der folgende Code implementiert die Trainingsschleife:
for i, tensordict_data in enumerate(collector):
for _ in range(OPTIM_STEPS):
advantage_module(tensordict_data)
replay_buffer.extend(tensordict_data.reshape(-1).cpu())
for _ in range(FRAMES_PER_BATCH // SUB_BATCH_SIZE):
data = replay_buffer.sample(SUB_BATCH_SIZE)
loss = loss_module(data.to(device))
loss_value = loss["loss_objective"] + loss["loss_critic"] + loss["loss_entropy"]
loss_value.backward()
optim.step()
optim.zero_grad()
scheduler.step()
if i % LOG_EVERY == 0:
with torch.no_grad():
rollout = env.rollout(FRAMES_PER_BATCH, actor)
reward_eval = rollout["next","reward"].sum()
#print(rollout["next","reward"].sum())
print(reward_eval)
rewards.append(reward_eval)
del rollout
Diese DataLab-Arbeitsmappe enthält den Code (wie oben gezeigt) für das Training eines RL-Agenten mit dem PPO-Algorithmus von TorchRL. Nutze sie als Ausgangspunkt für die Feinabstimmung der Parameter und die Verbesserung der Leistung des Agenten.
Algorithmen anpassen
TorchRL hat einen modularen Aufbau, der es ermöglicht, RL-Lösungen individuell anzupassen. Das Framework kümmert sich um die Schnittstellen zwischen den verschiedenen Komponenten. Um ihre Leistung zu testen und zu vergleichen, kannst du Umgebungen, verschiedene Richtlinien, Wiedergabepuffer und RL-Algorithmen einfügen und spielen. Wegen dieser Modularität:
- Du kannst verschiedene Komponenten auswechseln, ohne große Teile des Programms neu schreiben zu müssen.
- Einzelne Komponenten können auch unabhängig voneinander verändert werden, um individuelle Lösungen zu schaffen.
- Du kannst mit verschiedenen Modulen experimentieren und eine optimierte Lösung aufbauen.
Einige Beispiele für Anpassungen in TorchRL sind:
- Trainingsschleifen können mit Lernratenplanern, Loggern und benutzerdefinierten Metriken angepasst werden.
- Unterschiedliche Längen der Wiederholungspuffer können verwendet werden, um die Trainingsdauer anzupassen.
- Die Umgebung kann so angepasst werden, dass sie Skalierungs- und Normalisierungsfunktionen, Schrittzähler usw. enthält.
RL-Ausbildung visualisieren und debuggen
In den vorherigen Abschnitten wurde gezeigt, wie TorchRL-Module zum Trainieren von RL-Agenten verwendet werden können. In diesem Abschnitt besprechen wir, wie wir den Trainingsfortschritt überwachen und visualisieren können.
Überwachung des Ausbildungsfortschritts
Es ist hilfreich, während des Trainingsprozesses verschiedene Metriken aufzuzeichnen, um den Fortschritt zu überwachen. Pakete wie TensorBoard machen es einfach, die Ergebnisse während des Trainings direkt zu protokollieren. Mit dem SummaryWriter von TensorBoard kannst du ihn zum Beispiel innerhalb der Trainingsschleife aufrufen, um die Metriken zu protokollieren. Der folgende Pseudocode zeigt, wie das geht:
from torch.utils.tensorboard import SummaryWriter
writer = SummaryWriter(log_dir="training_logs")
for _ in training_data (): # training loop
loss = …
loss.backprop()
writer.add_scalar(“Loss - “, loss.item(), step)
…
writer.close()
Nach Abschluss des Trainings und der Protokollierung kannst du die Ergebnisse grafisch darstellen und visualisieren. Verwende zum Beispiel den Befehl tensorboard
, um den Trainingsfortschritt zu visualisieren .
tensorboard --logdir=”training_logs”
Fehlersuche mit TorchRL
Das Debugging ist wichtig, um die Interaktion des Agenten mit der Umgebung zu überprüfen. In einem ersten Schritt willst du den Aktionsraum und den Beobachtungsraum überprüfen. Die Dokumentation der Umgebung sollte die Spezifikationen für die Umgebung enthalten. In der Dokumentation von CartPole steht zum Beispiel, dass:
- Der Aktionsraum umfasst zwei diskrete Werte - 0 (für das Schieben des Wagens nach links) und 1 (für das Schieben des Wagens nach rechts)
- Der Beobachtungsraum hat 4 Werte:
- Warenkorbposition, mit einem Wert zwischen
- -4,8 und +4,8.
- Geschwindigkeit des Wagens, mit einem beliebigen reellen Zahlenwert
- Polwinkel, mit einem Wert zwischen -24 ° und +24 °
- Winkelgeschwindigkeit des Pols, mit einem beliebigen reellen Wert
Überprüfe die Beobachtungs- und Aktionsräume, um zu sehen, ob sie den erwarteten Werten entsprechen. Zum Beispiel:
print("Observation space: ", env.observation_spec)
print("Action space: ", env.action_spec)
Außerdem kannst du Stichproben aus den Beobachtungs- und Aktionsräumen ziehen und ihre Werte überprüfen:
print("Sample Observation:", base_env.observation_spec.sample().get("observation"))
print("Sample Action:", base_env.action_spec.sample())
Die Ausgabe ähnelt dem folgenden Beispiel:
Sample Observation: tensor([-4.5960e+00, 3.4028e+38, 2.2261e-02, 3.4028e+38])
Sample Action: tensor([1, 0])
Beachte, dass die 4 Zustandswerte innerhalb der zuvor angegebenen Bereiche liegen. Wiederhole die obigen Befehle ein paar Mal und achte darauf, dass die verschiedenen (zufällig abgetasteten) Ausgabewerte innerhalb der angegebenen Bereiche liegen.
Die beiden oben genannten Befehle basieren auf der Basisumgebung, die direkt aus Gymnasium importiert wird. In der Praxis verwenden wir die transformierte Umgebung, die Transformationen, wie z.B. Normalisierung, auf die ursprünglichen Tensorwerte anwendet. Wenn du also die umgewandelte TorchRL-Umgebung verwendest, um eine Stichprobe von Beobachtungen zu ziehen, kann es sein, dass ihre Werte nicht mehr in denselben Bereich fallen wie in der ursprünglichen Gymnasium-Umgebung.
Ziehe zum Beispiel eine Probe aus der transformierten Umgebung:
print("Sample Observation:", env.observation_spec.sample().get("observation"))
Die Ausgabe sieht so aus:
Sample Observation: tensor([-57.5869, nan, 4.5276, nan])
Beachte, dass die Werte für die Wagenposition und den Polwinkel außerhalb der Bereiche liegen. Das liegt daran, dass die Tensorwerte normalisiert wurden. Außerdem haben die Geschwindigkeit des Wagens und die Winkelgeschwindigkeit des Pols nan
Werte, weil der Agent noch nicht mit der Umgebung interagiert hat .
Visualisierung der Agentenleistung
Zusätzlich zum Aufzeichnen des Trainingsfortschritts kann es hilfreich sein, die Umgebung zu rendern und die Interaktionen des Agenten visuell zu beobachten. Das kann Aufschluss darüber geben, wie der Agent arbeitet.
Die pragmatischste Art, die Umgebung zu visualisieren, ist das Rendern eines Videos. Du brauchst ein paar zusätzliche Pakete:
torchvision
mit Multimedia-Dateien zu arbeitenav
um das Paketffmpeg
so zu verpacken, dass es mit PyTorch zusammenarbeiten kann .
pip install torchvision
pip install av==12.0.0
Nach der Schulung befolgst du diese vorbereitenden Schritte, um das Video zu rendern:
- Gib den (relativen) Pfad zum Speichern des Videos an.
- Initialisiere den Logger, um die Ergebnisse der Interaktionen des Agenten im CSV-Format zu speichern.
- Initialisiere den Videorekorder, damit er die CSV-Protokolle verwendet, um ein Video zu erstellen.
- Verändere die TorchRL-Umgebung so, dass sie den Videorekorder enthält.
…
# training loop
# for _ in …
…
…
from torchrl.record import CSVLogger, VideoRecorder
path = "./training_loop"
logger = CSVLogger(exp_name="dqn", log_dir=path, video_format="mp4")
video_recorder = VideoRecorder(logger, tag="video")
record_env = TransformedEnv(
GymEnv("CartPole-v1", from_pixels=True, pixels_only=False), video_recorder
)
Führe die (trainierte) Richtlinie in der Umgebung aus und lege die Renderings in der Videodatei ab:
record_env.rollout(max_steps=1000, policy=policy)
video_recorder.dump()
Nachdem du das Programm gestartet hast, findest du das Video in dem Verzeichnispfad (./training_loop
im obigen Ausschnitt), den du zuvor festgelegt hast. Hinweis:ie DataLab-Arbeitsmappe zur Implementierung des DQN mit TorchRL enthält nicht den Code zur Erstellung des Videos, da der Export von Videodateien mit einem Online-Notebook schwierig ist. Starte das Programm (und füge die oben genannten Schritte hinzu) auf einem lokalen Computer oder Server, um Videos aufzuzeichnen.
Best Practices für die Verwendung von TorchRL
Zum Schluss noch ein paar Best Practices. Hier sind meine Empfehlungen.
Beginne mit einfachen Umgebungen
Trotz der einfachen Entwicklung durch TorchRL bleibt es eine Herausforderung, RL-Agenten so zu trainieren, dass sie in komplexen Umgebungen gut funktionieren. Bevor du also versuchst, schwierige Probleme zu lösen, ist es wichtig, einfache Umgebungen wie CartPole zu lösen.
Die Modularität von TorchRL ermöglicht das Experimentieren mit verschiedenen Algorithmen und Parametern. Bevor du alternative Algorithmen und Anpassungsmöglichkeiten in der Praxis anwendest, ist es notwendig, einen Einblick in ihre Funktionsweise zu bekommen. Das geht am besten in einer einfachen Umgebung, in der die Auswirkungen der einzelnen Änderungen leicht zu beobachten sind.
Experimentiere mit Hyperparametern
Die Trainingsleistung von RL-Modellen hängt von verschiedenen Hyperparametern ab, z. B. von der Lernrate, der Explorationsrate, der Diskontierungsrate und anderen algorithmusspezifischen Hyperparametern, wie dem Clipping-Verhältnis für PPO. Zum Beispiel macht eine zu hohe Lernrate das Training instabil, während eine zu niedrige Lernrate zu lange braucht, um zu konvergieren.
Ebenso verhindert eine sehr hohe Erkundungsrate, dass das Training konvergiert, während eine zu niedrige Erkundungsrate den Agenten daran hindern kann, den optimalen Weg zu finden.
Es gibt keine Formel zur Bestimmung der richtigen Hyperparameterwerte. Es gibt zwar Richtlinien und empfohlene Werte für Standardumgebungen, aber sie gelten nicht für alle Probleme. Daher ist es notwendig, mit verschiedenen Methoden wie der Rastersuche oder der Zufallssuche zu experimentieren, um die besten Werte für die Hyperparameter zu ermitteln.
Es ist auch möglich, automatisierte Bibliotheken wie Weights & Biases Sweeps oder Optuna zu verwenden, umdie Trainingsleistung mit verschiedenen Hyperparameterkombinationen zu testen.
Vorgefertigte Algorithmen nutzen
Wie du in den vorherigen Beispielen gesehen hast, spart die Verwendung der vorgefertigten Module von TorchRL viel Entwicklungsaufwand. Die Alternative wäre, die gesamte Funktionalität von Grund auf neu zu entwickeln, was deutlich mehr Zeit und Kosten für die Entwicklung und Prüfung erfordern würde.
Da viele Entwickler die Module von TorchRL nutzen, profitieren sie auch davon, dass sie in verschiedenen Szenarien getestet wurden. Daher kannst du davon ausgehen, dass sie fehlerfreier sind als ein selbst entwickeltes Modul. Für die meisten Standardanwendungsfälle ist es daher ratsam, vorgefertigte Module zu verwenden.
Fazit
In diesem Artikel haben wir die grundlegenden Konzepte von TorchRL vorgestellt, einem PyTorch-basierten Framework zur Implementierung von RL-Algorithmen. Wir sahen auch praktische Beispiele für die Verwendung von TorchRL, um einfachere Lösungen wie Deep Q-Learning und komplexere Algorithmen wie PPO zu implementieren.
In einem nächsten Schritt kannst du diese Programme als Grundlage verwenden, um mit anderen Umgebungen und Algorithmen zu experimentieren.
Wenn du dein Verständnis von RL-Grundlagen und praktischen Anwendungen vertiefen möchtest, schau dir Reinforcement Learning with Gymnasium in Python an, um mehr praktische Erfahrungen mit Gymnasium-basierten Umgebungen zu sammeln.
Konzepte der Künstlichen Intelligenz (KI) in Python
Arun ist ein ehemaliger Startup-Gründer, der Spaß daran hat, neue Dinge zu entwickeln. Derzeit erforscht er die technischen und mathematischen Grundlagen der Künstlichen Intelligenz. Er liebt es, sein Wissen mit anderen zu teilen, also schreibt er darüber.
Neben dem DataCamp kannst du seine Veröffentlichungen auf Medium, Airbyte und Vultr lesen.
Lerne mehr über Reinforcement Learning mit diesen Kursen!
Kurs
Verstärkungslernen aus menschlichem Feedback (RLHF)
Kurs
Reinforcement Learning mit Gymnasium in Python
Der Blog
Top 30 Generative KI Interview Fragen und Antworten für 2024

Hesam Sheikh Hassani
15 Min.
Der Blog
Die 32 besten AWS-Interview-Fragen und Antworten für 2024

Der Blog
Lehrer/innen und Schüler/innen erhalten das Premium DataCamp kostenlos für ihre gesamte akademische Laufbahn
Der Blog
Die 20 besten Snowflake-Interview-Fragen für alle Niveaus

Nisha Arya Ahmed
20 Min.
Der Blog
2022-2023 DataCamp Classrooms Jahresbericht
Der Blog