Zum Inhalt springen

Cartpole-Beispiel

Bereit, Reinforcement Learning in Aktion zu sehen? In diesem Tutorial nehmen wir die klassische Balancier-Herausforderung an, bei der du beobachten kannst, wie deine KI lernt, eine Stange auf einem beweglichen Wagen aufrecht zu halten.

Die Cartpole-Herausforderung verbindet Einfachheit mit visuellem Feedback und ist damit perfekt für Reinforcement Learning geeignet. Du schiebst einen Wagen nach links oder rechts, und die Physik bestimmt, ob die daran befestigte Stange im Gleichgewicht bleibt oder umkippt. In jedem Zeitschritt trifft dein Agent eine Entscheidung, und du hast die Freude zu beobachten, wie dein Algorithmus allmählich die Aufgabe meistert.

Einrichten deines Projekts

Wir verwenden SciSharp/Gym.NET, um unsere simulierte physikalische Umgebung bereitzustellen.

Du kannst die Anleitung befolgen oder das vollständige Projekt herunterladen, wenn du möchtest.

Installieren wir die notwendigen Pakete:

Installation der notwendigen Pakete
dotnet add package RLMatrix
dotnet add package RLMatrix.Toolkit
dotnet add package Gym.NET
dotnet add package Gym.NET.Environments
dotnet add package Gym.NET.Rendering.WinForm

Aufbau der Umgebung

Hier ist unsere Implementierung der Cartpole-Umgebung:

CartPoleEnvironment.cs
using System;
using System.Threading.Tasks;
using Gym.Environments.Envs.Classic;
using Gym.Rendering.WinForm;
using RLMatrix.Toolkit;
using NumSharp;
namespace MyEnv
{
[RLMatrixEnvironment]
public partial class CartPoleEnvironment
{
private CartPoleEnv myEnv;
private float[] myState;
private int stepCounter;
private const int MaxSteps = 100000;
private bool isDone;
public CartPoleEnvironment()
{
InitialiseAsync();
}
private void InitialiseAsync()
{
myEnv = new CartPoleEnv(WinFormEnvViewer.Factory);
ResetEnvironment();
}
[RLMatrixObservation]
public float GetCartPosition() => myState[0];
[RLMatrixObservation]
public float GetCartVelocity() => myState[1];
[RLMatrixObservation]
public float GetPoleAngle() => myState[2];
[RLMatrixObservation]
public float GetPoleAngularVelocity() => myState[3];
[RLMatrixActionDiscrete(2)]
public void ApplyForce(int action)
{
if (isDone)
ResetEnvironment();
var (observation, reward, done, _) = myEnv.Step(action);
myEnv.Render();
myState = ToFloatArray(observation);
isDone = done;
stepCounter++;
if (stepCounter > MaxSteps)
isDone = true;
}
private float[] ToFloatArray(NDArray npArray)
{
double[] doubleArray = npArray.ToArray<double>();
return Array.ConvertAll(doubleArray, item => (float)item);
}
[RLMatrixReward]
public float CalculateReward()
{
return isDone ? 0 : 1;
}
[RLMatrixDone]
public bool IsEpisodeFinished()
{
return isDone;
}
[RLMatrixReset]
public void ResetEnvironment()
{
myEnv.Reset();
myState = new float[4] { 0, 0, 0, 0 };
isDone = false;
stepCounter = 0;
}
}
}

Einrichten des Trainings

Hier ist der Code für das Training, der unserem Agenten das Balancieren beibringen wird:

Program.cs
using RLMatrix.Agents.Common;
using RLMatrix;
using MyEnv;
Console.WriteLine("Starting cart-pole training...\n");
// Lernparameter konfigurieren
var learningSetup = new PPOAgentOptions(
batchSize: 8,
ppoEpochs: 8,
memorySize: 1000,
gamma: 0.99f,
width: 128,
entropyCoefficient: 0.01f,
lr: 1E-02f
);
// Umgebung erstellen und an den Agenten anhängen
var environment = new CartPoleEnvironment().RLInit(maxStepsSoft: 1200, maxStepsHard: 1200);
var env = new List<IEnvironmentAsync<float[]>> {
environment,
//new CartPoleEnvironment().RLInit() //auskommentieren, um mit mehreren Umgebungen zu trainieren
};
// Agenten initialisieren
var agent = new LocalDiscreteRolloutAgent<float[]>(learningSetup, env);
// Trainieren bis zur Konvergenz
for (int i = 0; i < 100000; i++)
{
await agent.Step();
}
Console.WriteLine("\nTraining complete!");
Console.ReadLine();

Die einfache Belohnung von +1 pro Zeitschritt ist täuschend leistungsstark. Deep-Reinforcement-Learning-Algorithmen optimieren natürlicherweise für langfristige Ziele und entdecken, dass subtile, präventive Anpassungen zu längeren Balancezeiten und höheren kumulativen Belohnungen führen.

PPO in RLMatrix: Was ist anders

Während DQN (aus unseren früheren Tutorials) für einfache Aufgaben effizienter bezüglich der Stichprobennutzung sein kann, liefert PPO im Allgemeinen ein stabileres Training ohne umfangreiches Hyperparameter-Tuning. Das macht es besonders gut geeignet für anspruchsvolle Steuerungsprobleme.

Der speichersparende Trick, den du kennen musst

Schau dir diese Zeile in unserem Trainingscode an:

var environment = new CartPoleEnvironment().RLInit(maxStepsSoft: 1200, maxStepsHard: 1200);

Diese unscheinbare Parameterkonfiguration enthält den Schlüssel zum Training mit sehr langen Episoden, ohne den GPU-Speicher zu überlasten. Lass mich erklären:

Was passiert, wenn wir diese Werte ändern?

var environment = new CartPoleEnvironment().RLInit(maxStepsSoft: 200, maxStepsHard: 1200);

Jetzt geschieht die Magie:

  1. Wir sammeln Belohnungen und berechnen Gradienten nur für die ersten 200 Schritte
  2. Die Simulation läuft natürlich bis zu 1200 Schritte oder bis zum Scheitern weiter
  3. Der GPU-Speicherverbrauch sinkt erheblich

Wenn du diese Konfiguration ausführst, überprüfe die Belohnungsgrafiken – du wirst feststellen, dass keine Belohnung 200 (unsere weiche Grenze) überschreitet, obwohl die Cartpole-Physik über diesen Punkt hinaus weiterläuft. Öffne deinen Task-Manager und beobachte die Speichereinsparungen in Echtzeit.

Diese Technik wird für komplexe Umgebungen, in denen Episoden unendlich lang laufen können, unverzichtbar. Anstatt mit Out-of-Memory-Fehlern abzustürzen, kontrollierst du genau, wie viel Rechenaufwand investiert wird, während die natürliche Umgebungsdynamik erhalten bleibt.

Den Lernprozess beobachten

Wenn du dieses Training startest, öffnet sich ein Fenster mit der Cartpole-Umgebung. Anfangs wird die Stange schnell umkippen – dein Agent hat keine Ahnung, was er tut. Aber innerhalb weniger Minuten wirst du eine bemerkenswerte Transformation beobachten:

  1. Zunächst macht der Agent zufällige Bewegungen ohne Strategie
  2. Dann beginnt er zu reagieren, wenn die Stange bereits fällt (zu spät!)
  3. Er lernt allmählich, Korrekturbewegungen immer früher auszuführen
  4. Schließlich macht er subtile, präventive Anpassungen und hält die Stange perfekt im Gleichgewicht

Diese sichtbare Progression macht Cartpole zu einem so befriedigenden Lernbeispiel. Du siehst nicht nur, wie sich Zahlen in einem Diagramm verbessern – du beobachtest, wie deine KI vor deinen Augen eine Fertigkeit entwickelt.

Teste dein Verständnis

Reinforcement Learning bei Cartpole verstehen

Nächste Schritte

In diesem Tutorial hast du:

  • Eine Echtzeit-Physiksimulation für Reinforcement Learning eingerichtet
  • Einen vollständigen Agenten implementiert, um ein klassisches Steuerungsproblem zu meistern
  • Gelernt, wie man Speicher effizient mit dem Soft/Hard-Beendigungstrick verwaltet
  • Verstanden, wie sich RLMatrix’s PPO-Implementierung von Standardimplementierungen unterscheidet

Als Nächstes werden wir die gleiche Umgebung ohne Toolkit implementieren, was dir Einblicke in das gibt, was hinter den eleganten Attributen steckt, die wir verwendet haben.