Kurs
Reinforcement Learning mit Gymnasium: Ein praktischer Leitfaden
Reinforcement Learning (RL) ist eines der drei wichtigsten Paradigmen des maschinellen Lernens, die anderen beiden sind überwachtes und unüberwachtes Lernen. Im RL lernt ein Agent, mit seiner Umgebung zu interagieren, um die kumulierten Belohnungen zu maximieren. Es lernt durch Versuch und Irrtum die optimale Aktion unter verschiedenen Umweltbedingungen. Reinforcement Learning with Human Feedback (RLHF) ermöglicht es dem Agenten, sein Verhalten bei jedem Schritt auf der Grundlage menschlicher Eingaben zu ändern.
RL löst Probleme wie selbstfahrende Autos, automatisierten Handel, Computerspieler in Videospielen, Trainingsroboter und mehr. Wenn tiefe neuronale Netze verwendet werden, um RL-Algorithmen anzuwenden, nennt man das Deep Reinforcement Learning.
In diesem Tutorial zeige ich dir, wie du mit Gymnasium, einer Open-Source-Python-Bibliothek zum Entwickeln und Vergleichen von Reinforcement-Learning-Algorithmen, loslegen kannst. Ich zeige dir, wie du es einrichtest, verschiedene RL-Umgebungen erkundest und mit Python einen einfachen Agenten zur Implementierung eines RL-Algorithmus baust.
Was ist ein Gymnasium?
Gymnasium ist eine Open-Source-Python-Bibliothek, die die Entwicklung von RL-Algorithmen unterstützt. Um Forschung und Entwicklung im RL zu erleichtern, bietet das Gymnasium:
- Eine große Vielfalt an Umgebungen, von einfachen Spielen bis hin zu Problemen, die reale Szenarien nachahmen.
- Optimierte APIs und Wrapper für die Schnittstelle zu den Umgebungen.
- Die Möglichkeit, eigene Umgebungen zu erstellen und die Vorteile des API-Frameworks zu nutzen.
Entwickler können RL-Algorithmen erstellen und API-Aufrufe für Aufgaben wie:
- Übergabe der vom Agenten gewählten Aktion an die Umwelt.
- Du kennst den Zustand der Umgebung und die Belohnung nach jeder Aktion.
- Trainiere das Modell.
- Testen der Leistung des Modells.
OpenAI's Gym gegen Farama's Gymnasium
OpenAI hat keine nennenswerten Ressourcen in die Entwicklung von Gym gesteckt, weil es keine geschäftliche Priorität für das Unternehmen war. Tie Farama Foundation wurde gegründet, um RL-Bibliotheken zu standardisieren und langfristig zu erhalten. Gymnasium ist die Abspaltung von OpenAI's Gym durch die Farama Foundation. Gymnasium 0.26.2 ist ein Drop-in-Ersatz für Gym 0.26.2. Mit dem Fork will Farama funktionale (zusätzlich zu den klassenbasierten) Methoden für alle API-Aufrufe hinzufügen, Vektorumgebungen unterstützen und die Wrapper verbessern. Das übergeordnete Ziel ist es, das Framework sauberer und effizienter zu machen.
Werde ein ML-Wissenschaftler
Einrichten der Turnhalle
Das Gymnasium benötigt bestimmte Versionen (nicht die neuesten Versionen) von verschiedenen abhängigen Programmen wie NumPy und PyTorch. Wir empfehlen daher, eine neue Conda- oder venv-Umgebung oder ein neues Notebook zu erstellen, um Gymnasium zu installieren, zu benutzen und RL-Programme auszuführen.
Du kannst diese DataLab-Arbeitsmappe verwenden, umw mit dem Lehrgang zu begleiten.
Installation der Turnhalle
Um Gymnasium auf einem Server oder einem lokalen Rechner zu installieren, führe aus:
$ pip install gymnasium
Um ein Notebook wie das Colab von Google oder das DataLab von DataCamp zu installieren, verwende:
!pip install gymnasium
Der obige Befehl installiert Gymnasium und die richtigen Versionen der Abhängigkeiten.
Erkundung der Umgebung des Gymnasiums
Ab November 2024 umfasst das Gymnasium über 60 eingebaute Umgebungen. Um die verfügbaren eingebauten Umgebungen zu durchsuchen, verwende die Funktion gym.envs.registry.all()
, wie im folgenden Beispiel gezeigt :
import gymnasium as gym
for i in gym.envs.registry.keys():
print(i)
Du kannst auch die Homepage des Gymnasiums besuchen. In der linken Spalte von lefindest du Links zu allen Umgebungen. Die Webseite jeder Umgebung enthält Details über sie, wie z.B. Aktionen, Zustände, etc.
Die Umgebungen sindin Kategorien wie Classic Control, Box2D und mehr unterteilt. Im Folgenden liste ich einige der gemeinsamen Umgebungen in jeder Gruppe auf:
- Klassische Kontrolle: Dies sind die klassischen Umgebungen, die in der RL-Entwicklung verwendet werden; sie bilden die Grundlage für viele Lehrbuchbeispiele. Sie bieten die richtige Mischung aus Komplexität und Einfachheit, um neue RL-Algorithmen zu testen und zu bewerten. Zu den klassischen Kontrollumgebungen im Gymnasium gehören:
- Akrobot
- Wagenständer
- Bergwagen Diskret
- Bergwagen Kontinuierlich
- Pendulum
- Box2D: Box2D ist eine 2D-Physik-Engine für Spiele. Zu den Umgebungen, die auf dieser Engine basieren, gehören einfache Spiele wie:
- Lunar Lander
- Autorennen
- ToyText: Das sind kleine und einfache Umgebungen, die oft zum Testen von RL-Algorithmen verwendet werden. Viele dieser Umgebungen basieren auf dem Modell einer kleinen Gitterwelt und einfachen Kartenspielen. Beispiele dafür sind:
- Blackjack
- Taxi
- Gefrorener See
- MuJoCo: Multi-Joint dynamics with Contact (MuJoCo) ist eine Open-Source-Physik-Engine, die Umgebungen für Anwendungen wie Robotik, Biomechanik, ML usw. simuliert. Zu den MuJoCo-Umgebungen im Gymnasium gehören:
- Ameise
- Trichter
- Humanoid
- Schwimmer
- Und mehr
Zusätzlich zu den eingebauten Umgebungen kann Gymnasium mit vielen externen Umgebungen verwendet werden, die dieselbe API nutzen.
In diesem Lernprogramm verwenden wir eine der klassischen Classic Control-Umgebungen. Um eine bestimmte Umgebung zu importieren, verwende den Befehl .make()
und gib den Namen der Umgebung als Argument an. Um zum Beispiel eine neue Umgebung auf Basis von CartPole (Version 1) zu erstellen, verwende den folgenden Befehl:
import gymnasium as gym
env = gym.make("CartPole-v1")
Konzepte des Verstärkungslernens im Gymnasium verstehen
Kurz gesagt, besteht Reinforcement Learning aus einem Agenten (wie einem Roboter), der mit seiner Umgebung interagiert. Eine Richtlinie entscheidet über die Handlungen des Agenten. Abhängig von den Aktionen des Agenten gibt die Umwelt in jedem Zeitschritt eine Belohnung (oder Strafe). Der Agent nutzt RL, um die optimale Strategie zu finden, die die Gesamtbelohnung des Agenten maximiert.
Komponenten einer RL-Umgebung
Im Folgenden sind die wichtigsten Komponenten einer RL-Umgebung aufgeführt:
- Umwelt: Das externe System, die Welt oder der Kontext. Der Agent interagiert mit der Umwelt in einer Reihe von Zeitschritten. In jedem Zeitschritt, basierend auf den Aktionen des Agenten, wird die Umgebung verändert:
- Gibt eine Belohnung (oder Strafe)
- Entscheidet über den nächsten Zustand
- Staat: Eine mathematische Darstellung der aktuellen Konfiguration der Umgebung.
- Der Zustand einer Pendelumgebung kann zum Beispiel die Position und die Winkelgeschwindigkeit des Pendels bei jedem Zeitschritt umfassen.
- Endzustand: Ein Zustand, der nicht zu neuen/anderen Zuständen führt.
- Agent: Der Algorithmus, der die Umgebung beobachtet und basierend auf dieser Beobachtung verschiedene Aktionen durchführt. Das Ziel des Agenten ist es, seine Belohnungen zu maximieren.
- Der Agent entscheidet zum Beispiel, wie stark und in welche Richtung er das Pendel schiebt.
- Beobachtung: Eine mathematische Darstellung der Sicht des Agenten auf die Umgebung, die z.B. mit Hilfe von Sensoren erfasst wird.
- Aktion: Die Entscheidung, die der/die Agent/in trifft, bevor er/sie zum nächsten Schritt übergeht. Die Aktion beeinflusst den nächsten Zustand der Umgebung und bringt dem Agenten eine Belohnung ein.
- Belohnung: Die Rückmeldung aus der Umwelt an den Agenten. Sie kann positiv oder negativ sein, abhängig von der Handlung und dem Zustand der Umgebung.
- Rückkehr: Die erwartete kumulative Rendite über zukünftige Zeitschritte. Belohnungen aus zukünftigen Zeitschritten können mit einem Diskontierungsfaktor abgezinst werden.
- Politik: Die Strategie des Agenten, welche Aktion er in verschiedenen Zuständen ausführen soll. Sie wird in der Regel als Wahrscheinlichkeitsmatrix P dargestellt, die Zustände auf Aktionen abbildet.
- Gegeben eine endliche Menge von m möglichen Zuständen und n möglichen Aktionen, Element Pmn in der Matrix bezeichnet die Wahrscheinlichkeit, dass die Aktion an in dem Zustand sm.
- Episode: Die Reihe von Zeitschritten vom (zufälligen) Anfangszustand bis zum Erreichen eines Endzustands des Agenten.
Beobachtungsraum und Handlungsraum
Die Beobachtung ist die Information, die der Agent über seine Umgebung sammelt. Ein Agent, z. B. ein Roboter, könnte mithilfe von Sensoren Informationen über die Umgebung sammeln. Im Idealfall sollte der Agent in der Lage sein, den kompletten Zustand zu beobachten, der alle Aspekte der Umgebung beschreibt. In der Praxis verwendet der Agent seine Beobachtungen als Stellvertreter für den Zustand. So entscheiden die Beobachtungen über die Handlungen des Agenten.
Ein Raum ist vergleichbar mit einer thematischen Menge (). Der Raum der Elemente X umfasst alle möglichen Instanzen von X. Der Raum von X definiert auch die Struktur (Syntax und Format) aller Elemente des Typs X. Jede Umgebung des Gymnasiums hat zwei Räume, den Aktionsraum action_space
und den Beobachtungsraum observation_space
. Sowohl der Aktions- als auch der Beobachtungsraum leiten sich von der übergeordneten Oberklasse gymnasium.spaces.Space
ab.
Beobachtungsraum
Der Beobachtungsraum ist der Raum, der alle möglichen Beobachtungen umfasst. Sie definiert auch das Format, in dem die Beobachtungen gespeichert werden. Der Beobachtungsraum wird in der Regel als ein Objekt der Datenpe Box dargestellt. Dies ist ein nDarray, das die Parameter der Beobachtungen beschreibt. Die Box legt die Grenzen der einzelnen Dimensionen fest. Du kannst den Beobachtungsraum für eine Umgebung mit der Methode observation_space
anzeigen:
print("observation space: ", env.observation_space)
Im Fall der Umgebung CartPole-v1
sieht die Ausgabe wie im folgenden Beispiel aus :
observation space: Box([-4.8 -inf -0.41887903 -inf], [4.8 inf 0.41887903 inf], (4,), float32)
In diesem Beispiel hat der CartPole-v1
Beobachtungsraum 4 Dimensionen. Die 4 Elemente des Beobachtungsfeldes sind:
- Position des Wagens - variiert zwischen -4,8 und +4,8
- Geschwindigkeit des Wagens - liegt zwischen - bis +
- Der Winkel des Pols - variiert zwischen -0,4189 und +0,4189
- Die Winkelgeschwindigkeit der Pole - liegt zwischen - bis +
Um ein Beispiel für ein einzelnes Beobachtungsfeld zu sehen, verwende den Befehl .reset()
.
observation, info = env.reset()
print("observation: ", observation)
Im Fall der Umgebung CartPole-v1
sieht die Ausgabe wie im folgenden Beispiel aus :
[ 0.03481963 -0.0277232 0.01703267 -0.04870504]
Die vier Elemente dieses Feldes entsprechen den vier beobachteten Größen (Wagenposition, Wagengeschwindigkeit, Polwinkel, Polwinkelgeschwindigkeit), wie bereits erklärt.
Aktionsraum
Der Aktionsraum umfasst alle möglichen Aktionen, die der Agent ausführen kann. Der Aktionsraum definiert auch das Format, in dem Aktionen dargestellt werden. Du kannst den Aktionsraum für eine Umgebung mit der Methode action_space
anzeigen:
print("action space: ", env.action_space)
Im Fall der Umgebung CartPole-v1
sieht die Ausgabe wie im folgenden Beispiel aus :
action space: Discrete(2)
In der Umgebung von CartPole-v1
ist der Aktionsraum diskret. Es gibt insgesamt zwei Aktionen, die der Agent ausführen kann:
- 0: Schieb den Wagen nach links
- 1: Schieb den Wagen nach rechts
Baue deinen ersten RL-Agenten mit Gymnasium
In den vorherigen Abschnitten haben wir die grundlegenden Konzepte von RL und Gymnasium kennengelernt. Dieser Abschnitt zeigt dir, wie du mit Gymnasium einen RL-Agenten erstellen kannst.
Erstellen und Zurücksetzen der Umgebung
Der erste Schritt besteht darin, eine Instanz der Umgebung zu erstellen. Um neue Umgebungen zu erstellen, verwende die Methode .make()
.
env = gym.make('CartPole-v1')
Die Interaktionen des Agenten verändern den Zustand der Umgebung. Die Methode .reset()
setzt die Umgebung auf einen Ausgangszustand zurück. Standardmäßig wird die Umgebung mit einem zufälligen Zustand initialisiert. Du kannst einen SEED
Parameter mit der Methode .reset()
verwenden, um die Umgebung bei jedem Programmstart in denselben Zustand zu versetzen. Der folgende Code zeigt, wie man das macht:
SEED = 1111
env.reset(seed=SEED)
Auch bei der Auswahl der Aktionen gibt es Zufälle. Um diese Zufälligkeit zu kontrollieren und einen vollständig reproduzierbaren Trainingspfad zu erhalten, können wir die Zufallsgeneratoren von NumPy und PyTorch setzen:
np.random.seed(SEED)
torch.manual_seed(SEED)
Zufällige versus intelligente Aktionen
In jedem Schritt eines Markov-Prozesses kann der Agent zufällig eine Aktion wählen und die Umgebung erkunden, bis er einen Endzustand erreicht. Indem du Aktionen nach dem Zufallsprinzip auswählst:
- Es kann sehr lange dauern, bis der Endzustand erreicht ist.
- Die kumulierten Belohnungen sind viel geringer, als sie hätten sein können.
Es ist effizienter, den Agenten darauf zu trainieren, die Auswahl seiner Handlungen auf der Grundlage früherer Erfahrungen (mit der Umwelt) zu optimieren, um den langfristigen Nutzen zu maximieren.
Der untrainierte Agent beginnt mit zufälligen Aktionen, die auf einer zufällig initialisierten Richtlinie basieren. Diese Politik wird normalerweise als neuronales Netz dargestellt. Während des Trainings lernt der Agent die optimale Strategie, die die Belohnungen maximiert. Im RL wird der Trainingsprozess auch als Richtlinienoptimierung bezeichnet.
Es gibt verschiedene Methoden der Politikoptimierung. Die Bellman-Gleichungen beschreiben, wie man den Wert von RL-Politiken berechnet und die optimale Politik bestimmt. In diesem Lernprogramm verwenden wir eine einfache Technik, die wir " Policy Gradients" nennen. Es gibt auch andere Methoden, wie zum Beispiel die Proximal Policy Optimization (PPO).
Implementierung eines einfachen Policy Gradient Agent
Um einen RL-Agenten zu bauen, der Policy-Gradienten verwendet, erstellen wir ein neuronales Netz, um die Policy zu implementieren, schreiben Funktionen, um die Erträge und Verluste aus den schrittweisen Belohnungen und den Aktionswahrscheinlichkeiten zu berechnen, und aktualisieren die Policy iterativ mit Standard-Backpropagationstechniken.
Einrichten des Policy-Netzwerks
Wir verwenden ein neuronales Netzwerk, um die Politik umzusetzen. Weil CartPole-v1
eine einfache Umgebung ist, verwenden wir ein neuronales Netzwerk mit:
- Die Eingangsdimensionen entsprechen der Dimensionalität des Beobachtungsraums der Umgebung.
- Eine einzelne versteckte Schicht mit 64 Neuronen.
- Die Ausgangsdimensionen entsprechen der Dimensionalität des Aktionsraums der Umgebung.
Die Funktion des Politiknetzwerks besteht also darin, beobachtete Zustände auf Aktionen abzubilden. Ausgehend von einer Eingangsbeobachtung sagt sie die richtige Handlung voraus. Der folgende Code implementiert das Policy-Netzwerk:
class PolicyNetwork(nn.Module):
def __init__(self, input_dim, hidden_dim, output_dim, dropout):
super().__init__()
self.layer1 = nn.Linear(input_dim, hidden_dim)
self.layer2 = nn.Linear(hidden_dim, output_dim)
self.dropout = nn.Dropout(dropout)
def forward(self, x):
x = self.layer1(x)
x = self.dropout(x)
x = F.relu(x)
x = self.layer2(x)
return x
Belohnungssammlung und der Vorwärtspass
Wie bereits erwähnt, vergibt die Umwelt in jedem Schritt des Markov-Prozesses eine Belohnung, die auf der Aktion und dem Zustand des Agenten basiert. Das Ziel im RL ist es, die Gesamtrendite zu maximieren.
- Die Rendite in jedem Zeitschritt ist die kumulierte Summe der Belohnungen, die von Anfang an bis zu diesem Schritt erzielt wurden.
- Die Gesamtrendite in jeder Episode ergibt sich aus der Summe aller schrittweisen Belohnungen dieser Episode. Die Gesamtrendite ist also die Rendite des letzten Zeitschritts (wenn der Agent einen Endzustand erreicht).
In der Praxis ist es üblich, beim Sammeln von Belohnungen:
- Passe zukünftige Belohnungen mit einem Abzinsungsfaktor an.
- Normalisiere die Reihe der schrittweisen Rückgaben, um eine reibungslose und stabile Ausbildung zu gewährleisten.
Der folgende Code zeigt, wie man das macht:
def calculate_stepwise_returns(rewards, discount_factor):
returns = []
R = 0
for r in reversed(rewards):
R = r + R * discount_factor
returns.insert(0, R)
returns = torch.tensor(returns)
normalized_returns = (returns - returns.mean()) / returns.std()
return normalized_returns
Der Vorwärtsdurchlauf besteht darin, den Agenten auf der Grundlage der aktuellen Strategie laufen zu lassen, bis er einen Endzustand erreicht, und die schrittweisen Belohnungen und Aktionswahrscheinlichkeiten zu sammeln. Die folgenden Schritte erklären, wie du den Vorwärtspass einführst:
- Setze die Umgebung auf einen Ausgangszustand zurück.
- Initialisiere Puffer, um die Aktionswahrscheinlichkeiten, die Belohnungen und den kumulierten Ertrag zu speichern
- Verwende die Funktion
.step()
, um den Agenten iterativ in der Umgebung auszuführen, bis er beendet wird: - Erhalte die Beobachtung des Zustands der Umgebung.
- Erhalte die Aktion, die von der Richtlinie auf der Grundlage der Beobachtung vorhergesagt wird.
- Nutze die Funktion
Softmax
, um die Wahrscheinlichkeit zu schätzen, mit der du die vorhergesagte Handlung ausführst. - Simuliere eine kategoriale Wahrscheinlichkeitsverteilung, die auf diesen geschätzten Wahrscheinlichkeiten basiert.
- Probiere diese Verteilung aus, um die Aktion des Agenten zu erhalten.
- Schätze die logarithmische Wahrscheinlichkeit der gesampelten Aktion aus der simulierten Verteilung.
- Füge die logarithmischen Wahrscheinlichkeiten der Aktionen und die Belohnungen aus jedem Schritt an ihre jeweiligen Puffer an.
- Schätze die normalisierten und diskontierten Werte der Renditen bei jedem Schritt auf der Grundlage der Belohnungen.
def forward_pass(env, policy, discount_factor):
log_prob_actions = []
rewards = []
done = False
episode_return = 0
policy.train()
observation, info = env.reset()
while not done:
observation = torch.FloatTensor(observation).unsqueeze(0)
action_pred = policy(observation)
action_prob = F.softmax(action_pred, dim = -1)
dist = distributions.Categorical(action_prob)
action = dist.sample()
log_prob_action = dist.log_prob(action)
observation, reward, terminated, truncated, info = env.step(action.item())
done = terminated or truncated
log_prob_actions.append(log_prob_action)
rewards.append(reward)
episode_return += reward
log_prob_actions = torch.cat(log_prob_actions)
stepwise_returns = calculate_stepwise_returns(rewards, discount_factor)
return episode_return, stepwise_returns, log_prob_actions
Aktualisierung der Politik aufgrund von Belohnungen
Der Verlust stellt die Größe dar, auf die wir den Gradientenabstieg anwenden. Das Ziel im RL ist es, die Erträge zu maximieren. Wir verwenden also den erwarteten Rückgabewert als Ersatz für den Verlust. Der erwartete Renditewert wird als Produkt aus den schrittweise erwarteten Renditen und der logarithmischen Wahrscheinlichkeit der schrittweisen Aktionen berechnet. Der folgende Code berechnet den Verlust:
def calculate_loss(stepwise_returns, log_prob_actions):
loss = -(stepwise_returns * log_prob_actions).sum()
return loss
Um die Richtlinie zu aktualisieren, führst du Backpropagation in Bezug auf die Verlustfunktion durch. Die folgende Methode update_policy()
ruft die Methode calculate_loss()
auf. Dann wird dieser Verlust durch Backpropagation verarbeitet, um die Parameter, d.h. die Modellgewichte des Policy-Netzwerks, zu aktualisieren.
def update_policy(stepwise_returns, log_prob_actions, optimizer):
stepwise_returns = stepwise_returns.detach()
loss = calculate_loss(stepwise_returns, log_prob_actions)
optimizer.zero_grad()
loss.backward()
optimizer.step()
return loss.item()
Die Aktualisierung der Strategie auf der Grundlage des Gradienten der Renditen wird als Policy-Gradient-Methodebezeichnet.
Schulung der Politik
Wir haben jetzt alle Komponenten, die wir brauchen, um die Politik zu trainieren und zu bewerten. Wir implementieren die Trainingsschleife wie in den folgenden Schritten erklärt:
Bevor wir beginnen, deklarieren wir die Hyperparameter, instanziieren eine Richtlinie und erstellen einen Optimierer:
- Deklariere die Hyperparameter als Python-Konstanten:
MAX_EPOCHS
ist die maximale Anzahl an Iterationen, die wir bereit sind, für das Training der Strategie durchzuführen.DISCOUNT_FACTOR
entscheidet über die relative Bedeutung der Belohnungen aus zukünftigen Zeitschritten. Ein Diskontierungsfaktor von 1 bedeutet, dass alle Belohnungen gleich wichtig sind, während ein Wert von 0 bedeutet, dass nur die Belohnung des aktuellen Zeitschritts wichtig ist.N_TRIALS
ist die Anzahl der Episoden, über die wir den Durchschnitt der Erträge ermitteln, um die Leistung des Agenten zu bewerten. Wir entscheiden, dass das Training erfolgreich ist, wenn die durchschnittliche Rendite überN_TRIALS
Episoden über dem Schwellenwert liegt .REWARD_THRESHOLD
: Wenn die Politik eine Rendite über dem Schwellenwert erzielen kann, gilt sie als erfolgreich.DROPOUT
bestimmt den Anteil der Gewichte, der zufällig auf Null gesetzt werden soll. Die Dropout-Funktion setzt zufällig einen Teil der Modellgewichte auf Null. Dadurch wird die Abhängigkeit von bestimmten Neuronen verringert und eine Überanpassung verhindert, was das Netz robuster macht.LEARNING_RATE
entscheidet darüber, wie stark die Richtlinienparameter in jedem Schritt geändert werden können. Die Aktualisierung der Parameter in jeder Iteration ist das Produkt aus dem Gradienten und der Lernrate.- Definiere die Richtlinie als eine Instanz der Klasse
PolicyNetwork
(die zuvor implementiert wurde). - Erstelle einen Optimierer mit dem Adam-Algorithmus und der Lernrate.
Um die Strategie zu trainieren, führen wir die Trainingsschritte iterativ durch, bis der durchschnittliche Ertrag (über N_TRIALS
) größer ist als die Belohnungsschwelle:
- Führe den Vorwärtspass für jede Episode einmal durch. Erfasse die logarithmische Wahrscheinlichkeit von Aktionen, die schrittweisen Renditen und die Gesamtrendite aus dieser Episode. Sammle die episodischen Erträge in einem Array.
- Berechne den Verlust anhand der logarithmischen Wahrscheinlichkeiten und der schrittweisen Erträge. Führe die Backpropagation auf den Verlust aus. Nutze den Optimierer, um die Richtlinienparameter zu aktualisieren.
- Überprüfe, ob die durchschnittliche Rendite über
N_TRIALS
die Belohnungsschwelle überschreitet .
Der folgende Code setzt diese Schritte um:
def main():
MAX_EPOCHS = 500
DISCOUNT_FACTOR = 0.99
N_TRIALS = 25
REWARD_THRESHOLD = 475
PRINT_INTERVAL = 10
INPUT_DIM = env.observation_space.shape[0]
HIDDEN_DIM = 128
OUTPUT_DIM = env.action_space.n
DROPOUT = 0.5
episode_returns = []
policy = PolicyNetwork(INPUT_DIM, HIDDEN_DIM, OUTPUT_DIM, DROPOUT)
LEARNING_RATE = 0.01
optimizer = optim.Adam(policy.parameters(), lr = LEARNING_RATE)
for episode in range(1, MAX_EPOCHS+1):
episode_return, stepwise_returns, log_prob_actions = forward_pass(env, policy, DISCOUNT_FACTOR)
_ = update_policy(stepwise_returns, log_prob_actions, optimizer)
episode_returns.append(episode_return)
mean_episode_return = np.mean(episode_returns[-N_TRIALS:])
if episode % PRINT_INTERVAL == 0:
print(f'| Episode: {episode:3} | Mean Rewards: {mean_episode_return:5.1f} |')
if mean_episode_return >= REWARD_THRESHOLD:
print(f'Reached reward threshold in {episode} episodes')
break
Zum Schluss rufst du die Funktion main()
auf, um die Richtlinie zu trainieren:
main()
Ubenutze diese DataLab Arbeitsmappe, um denden obigen Algorithmus direkt auszuführen und die CartPole-Umgebung mit RL zu lösen.
Fortgeschrittene Techniken im Gymnasium
Nachdem wir gezeigt haben, wie man einen RL-Algorithmus implementiert, besprechen wir nun einige fortgeschrittene Techniken, die in der Praxis häufig verwendet werden.
Vorgefertigte Architekturen verwenden
RL-Algorithmen von Grund auf zu implementieren ist ein langwieriger und schwieriger Prozess, vor allem bei komplexen Umgebungen und hochmodernen Richtlinien.
Eine praktischere Alternative ist der Einsatz von Softwarewie Stable Baselines3. Es verfügt über bewährte Implementierungen von RL-Algorithmen. Es enthält vortrainierte Agenten, Trainingsskripte, Bewertungswerkzeuge und Module zum Erstellen von Diagrammen und Aufzeichnen von Videos.
Ray RLib ist ein weiteres beliebtes Tool für RL. RLib ist als skalierbare Lösung konzipiert, die es einfach macht, RL-Algorithmen auf Multi-GPU-Systemen zu implementieren. Es unterstützt auch Multi-Agenten-RL, was neue Möglichkeiten eröffnet:
- Unabhängiges Lernen von Multi-Agenten: Jeder Agent behandelt andere Agenten als Teil der Umgebung.
- Kollaboratives Multi-Agenten-Training: Eine Gruppe von Agenten teilt dieselben Richtlinien und Wertfunktionen und lernt parallel von den Erfahrungen der anderen.
- Gegensätzliche Ausbildung: Agenten (oder Gruppen von Agenten) treten in wettbewerbsfähigen, spielähnlichen Umgebungen gegeneinander an.
Sowohl mit RLib als auch mit Stable Baselines3 kannst du Umgebungen aus OpenAI Gymnasium importieren und verwenden.
Benutzerdefinierte Umgebungen
Umgebungen, die mit Gymnasium verpackt sind, sind die richtige Wahl, um neue RL-Strategien und Ausbildungsrichtlinien zu testen. Für die meisten praktischen Anwendungen musst du jedoch eine Umgebung schaffen und verwenden, die genau das Problem widerspiegelt, das du lösen willst. Du kannst Gymnasium benutzen, um eine eigene Umgebung zu schaffen. Der Vorteil der benutzerdefinierten Umgebungen von Gymnasium ist, dass viele externe Tools wie RLib und Stable Baselines3 bereits für die Arbeit mit der API-Struktur von Gymnasium konfiguriert sind.
Um eine benutzerdefinierte Umgebung in Gymnasium zu erstellen, musst du sie definieren:
- Der Beobachtungsraum.
- Die Endbedingungen.
- Die Menge der Aktionen, aus denen der Agent wählen kann.
- Wie man die Umgebung initialisiert (wenn die Funktion
reset()
aufgerufen wird) . - Wie die Umwelt den nächsten Zustand angesichts der Aktionen des Agenten bestimmt (wenn die Funktion
step()
aufgerufen wird) .
Mehr dazu erfährst du in der Anleitung für dasGymnasium zum Erstellen von benutzerdefinierten Umgebungen.
Bewährte Praktiken für die Nutzung des Gymnasiums
Experimentiere mit verschiedenen Umgebungen
Der Code in diesem Tutorial zeigt, wie man den Policy-Gradient-Algorithmus in der CartPole-Umgebung implementiert. Dies ist eine einfache Umgebung mit einem diskreten Aktionsraum. Um RL besser zu verstehen, raten wir dir, denselben Policy-Gradient-Algorithmus (und andere Algorithmen wie PPO) in anderen Umgebungen anzuwenden.
Die Pendel-Umgebung hat zum Beispiel einen kontinuierlichen Aktionsraum. Es besteht aus einer einzigen Eingabe, die als kontinuierliche Variable dargestellt wird - das Drehmoment (Größe und Richtung des Drehmoments), das auf das Pendel in einem bestimmten Zustand wirkt. Dieses Drehmoment kann einen beliebigen Wert zwischen -2 und +2 annehmen.
Das Experimentieren mit verschiedenen Algorithmen in unterschiedlichen Umgebungen hilft dir, verschiedene Arten von RL-Lösungen und ihre Herausforderungen besser zu verstehen.
Trainingsfortschritt überwachen
RL-Umgebungen bestehen oft aus Robotern, Pendeln, Bergautos, Videospielen, etc. Die Visualisierung der Aktionen des Agenten in der Umgebung ermöglicht ein besseres intuitives Verständnis der Leistung der Strategie.
In Gymnasium visualisiert die Methode env.render()
die Interaktionen des Agenten mit seiner Umgebung. Sie zeigt grafisch den aktuellen Zustand der Umgebung an - Spielbildschirme, die Position des Pendels oder der Wagenstange usw. Visuelle Rückmeldungen über die Aktionen des Agenten und die Reaktionen der Umgebung helfen dabei, die Leistung des Agenten und seinen Fortschritt im Trainingsprozess zu überwachen.
Es gibt vier Darstellungsmodi: "human", "rgb_array", "ansi" und "rgb_array_list". Um die Leistung des Agenten zu visualisieren, verwende den "menschlichen" Rendermodus. Der Rendermodus wird bei der Initialisierung der Umgebung festgelegt. Zum Beispiel:
env = gym.make(‘CartPole-v1’, render_mode=’human’)
Um das Rendering durchzuführen, rufe die Methode .render()
nach jeder Aktion des Agenten auf (durch Aufruf der Methode .step()
). Der folgende Pseudocode veranschaulicht, wie das geht:
while not done:
…
step, reward, terminated, truncated, info = env.step(action.item())
env.render()
…
Fehlersuche bei häufigen Fehlern
Gymnasium macht es einfach, Schnittstellen zu komplexen RL-Umgebungen zu schaffen. Allerdings ist es eine ständig aktualisierte Software mit vielen Abhängigkeiten. Deshalb ist es wichtig, auf ein paar häufige Fehler zu achten.
Versionsabweichungen
- Die Version des Gymnasiums stimmt nicht überein: Das Softwarepaket Farama's Gymnasium wurde von OpenAI's Gym in der Version 0.26.2 abgekupfert. Zwischen älteren Gym-Versionen und den neuen Versionen von Gymnasium gibt es ein paar Änderungen. Viele öffentlich verfügbare Implementierungen basieren auf älteren Gym-Versionen und funktionieren möglicherweise nicht direkt mit der neuesten Version. In solchen Fällen ist es notwendig, entweder die Installation auf eine ältere Version zurückzusetzen oder den Code an die neuere Version anzupassen.
- Die Umgebungsversion stimmt nicht überein: In vielen Gymnasien gibt es verschiedene Versionen. Es gibt zum Beispiel zwei CartPole-Umgebungen -
CartPole-v1
undCartPole-v0
. Obwohl das Verhalten der Umgebung in beiden Versionen gleich ist, können einige Parameter wie die Episodenlänge, die Belohnungsschwelle usw. unterschiedlich sein. Eine Richtlinie, die in einer Version trainiert wurde, funktioniert möglicherweise in einer anderen Version derselben Umgebung nicht so gut. Du musst die Trainingsparameter aktualisieren und die Richtlinie für jede Umgebungsversion neu trainieren. - Die Versionen der Abhängigkeiten stimmen nicht überein: Gymnasium ist abhängig von Abhängigkeiten wie NumPy und PyTorch. Die neuesten Versionen dieser Abhängigkeiten sind
numpy 2.1.3
undtorch 2.5.1
(Stand: Dezember 2024). Das Gymnasium funktioniert jedoch am besten mittorch 1.13.0
undnumpy 1.23.3
. Es kann zu Problemen kommen, wenn du Gymnasium in einer Umgebung installierst, in der diese Abhängigkeiten vorinstalliert sind. Wir empfehlen, Gymnasium in einer neuen Conda-Umgebung zu installieren und damit zu arbeiten.
Konvergenzprobleme
- Hyperparameter: Wie andere Algorithmen des maschinellen Lernens sind auch RL-Strategien empfindlich gegenüber Hyperparametern wie der Lernrate, dem Diskontierungsfaktor usw. Wir empfehlen, mit den Hyperparametern zu experimentieren und sie manuell einzustellen oder automatisierte Techniken wie die Rastersuche und die Zufallssuche zu verwenden.
- Erkundung versus Ausbeutung: Bei einigen Politikklassen (z. B. PPO) verfolgt der Agent eine zweigleisige Strategie: Er erkundet die Umgebung, um neue Pfade zu entdecken, und wählt einen gierigen Ansatz, um die Belohnungen auf der Grundlage der bisher bekannten Pfade zu maximieren. Wenn sie zu viel erforscht, konvergiert die Politik nicht. Umgekehrt versucht es nie den optimalen Weg, wenn es nicht genug erforscht. Es ist also wichtig, das richtige Gleichgewicht zwischen Erkundung und Ausbeutung zu finden. Es ist auch üblich, die Erkundung in früheren Episoden und die Ausbeutung in späteren Episoden während der Ausbildung zu priorisieren.
Instabilität der Ausbildung
- Große Lernraten: Wenn die Lernrate zu hoch ist, werden die Politikparameter bei jedem Schritt stark aktualisiert. Das könnte dazu führen, dass die optimale Menge an Werten nicht erreicht wird. Eine gängige Lösung besteht darin, die Lernrate allmählich zu verringern, um kleinere und stabilere Aktualisierungen zu gewährleisten, während das Training konvergiert.
- Übermäßiges Erforschen: Zu viel Zufälligkeit (Entropie) bei der Aktionsauswahl verhindert Konvergenz und führt zu großen Schwankungen der Verlustfunktion zwischen den einzelnen Schritten. Um einen stabilen und konvergenten Trainingsprozess zu haben, musst du ein Gleichgewicht zwischen Erkundung und Ausbeutung herstellen.
- Falsche Wahl des Algorithmus: Einfache Algorithmen wie Policy Gradient können in komplexen Umgebungen mit großen Aktions- und Zustandsräumen zu instabilem Training führen. In solchen Fällen empfehlen wir die Verwendung robusterer Algorithmen wie PPO und Trust Region Policy Optimization (TRPO). Diese Algorithmen vermeiden große Aktualisierungen der Richtlinien in jedem Schritt und können stabiler sein.
- Zufälligkeit: RL-Algorithmen sind bekanntermaßen empfindlich gegenüber Anfangszuständen und der Zufälligkeit bei der Aktionsauswahl. Wenn ein Trainingslauf instabil ist, kann er manchmal durch einen anderen Zufallswert oder durch eine Neuinitialisierung der Strategie stabilisiert werden.
Fazit
In diesem Tutorial haben wir die Grundprinzipien von RL erkundet, Gymnasium als Softwarepaket mit einer sauberen API zur Anbindung an verschiedene RL-Umgebungen besprochen und gezeigt, wie man ein Python-Programm schreibt, um einen einfachen RL-Algorithmus zu implementieren und ihn in einer Gymnasium-Umgebung anzuwenden.
Nachdem du die Grundlagen in diesem Tutorial verstanden hast, empfehle ich dir, die Konzepte des RL in den Umgebungen des Gymnasiums anzuwenden, um praktische Probleme wie die Optimierung von Taxirouten oder Simulationen des Aktienhandels zu lösen.
Fähigkeiten im Bereich Machine Learning aufbauen
FAQs
Was ist die Rolle des Gymnasiums beim Verstärkungslernen?
Gymnasium kommt mit vielen vorgefertigten Umgebungen zum Testen und Entwickeln von RL-Algorithmen. Sie vereinheitlicht die Schnittstelle für diese Umgebungen und neue benutzerdefinierte Umgebungen. Das macht es einfacher, RL-Algorithmen zu implementieren und zu bewerten.
Bist du auf die eingebauten Umgebungen beschränkt, wenn du OpenAI Gymnasium benutzt?
Nein. Zusätzlich zu den über 60 vorgefertigten Umgebungen kannst du in Gymnasium neue Umgebungen erstellen, indem du ihren Zustand und ihre Aktionsräume erklärst und festlegst, wie die Umgebung auf verschiedene Aktionen reagieren soll.
Was ist der Unterschied zwischen Gym und Gymnasium?
Kurz gesagt ist Gymnasium, das von der Farama Foundation gepflegt wird, die neue und verbesserte Version von Gym, das von OpenAI nicht mehr gepflegt wird. Gymnasium wird voraussichtlich als Ersatz für Gym 0.26.2 funktionieren.
Was ist der Unterschied zwischen politikbasierten und wertbasierten RL-Methoden?
Bei richtlinienbasierten Methoden, wie z.B. Policy-Gradienten, ändert der Agent direkt die Parameter der Strategie, um diejenige Strategie zu finden, die zum maximalen erwarteten Ertrag führt.
Bei wertbasierten Methoden wird der Agent auf die Wertfunktion trainiert. Das Erlernen der optimalen Wertfunktion hilft bei der Ableitung der optimalen Politik.
Ist die manuelle Programmierung von Algorithmen der beste und einzige Weg, um RL-Probleme zu lösen?
Code von Grund auf zu schreiben ist der beste Weg, um verschiedene RL-Algorithmen zu verstehen. Für den Produktionseinsatz gibt es Tools wie Stable Baselines3, RLib und CleanRL. Diese Tools enthalten vorgefertigte Implementierungen gängiger RL-Algorithmen, die du je nach Umgebung konfigurieren und feinjustieren musst.
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
Deep Reinforcement Learning in Python
Kurs
Reinforcement Learning from Human Feedback (RLHF)
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
Die 20 besten Snowflake-Interview-Fragen für alle Niveaus
Nisha Arya Ahmed
20 Min.