小車-桿平衡示例
準備好親眼見證強化學習的實際應用了嗎?在本教程中,我們將挑戰經典的平衡任務,你將觀察到AI如何學會在移動小車上保持一根桿子直立。
小車-桿平衡挑戰結合了簡單性和視覺反饋,使其成為強化學習的完美示例。你向左或向右推動小車,物理定律決定了附著的桿子是保持平衡還是倒下。每個時間步,你的智能體做出決策,而你可以滿意地觀察你的算法如何逐漸掌握這項任務。
項目設置
我們將使用SciSharp/Gym.NET提供模擬物理環境。
您可以跟隨教程操作,也可以下載完整項目。
讓我們安裝必要的包:
dotnet add package RLMatrixdotnet add package RLMatrix.Toolkitdotnet add package Gym.NETdotnet add package Gym.NET.Environmentsdotnet add package Gym.NET.Rendering.WinForm
構建環境
以下是我們的小車-桿環境實現:
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; } }}
設置訓練
現在是教導我們的智能體平衡的訓練代碼:
using RLMatrix.Agents.Common;using RLMatrix;using MyEnv;
Console.WriteLine("Starting cart-pole training...\n");
// 配置學習參數var learningSetup = new PPOAgentOptions( batchSize: 8, ppoEpochs: 8, memorySize: 1000, gamma: 0.99f, width: 128, entropyCoefficient: 0.01f, lr: 1E-02f);
// 創建環境並連接到智能體var environment = new CartPoleEnvironment().RLInit(maxStepsSoft: 1200, maxStepsHard: 1200);var env = new List<IEnvironmentAsync<float[]>> { environment, //new CartPoleEnvironment().RLInit() //取消註釋可使用多環境訓練};
// 初始化智能體var agent = new LocalDiscreteRolloutAgent<float[]>(learningSetup, env);
// 訓練直至收斂for (int i = 0; i < 100000; i++){ await agent.Step();}
Console.WriteLine("\nTraining complete!");Console.ReadLine();
每時間步+1的簡單獎勵出奇地有效。深度強化學習算法自然會優化長期目標,發現微妙、預防性的調整能導致更長的平衡時間和更高的累積獎勵。
RLMatrix中的PPO:有何不同
雖然DQN(我們早期教程中的算法)對簡單任務可能更具樣本效率,但PPO通常提供更穩定的訓練,無需大量超參數調整。這使其特別適合具有挑戰性的控制問題。
你需要知道的記憶體節省技巧
看看我們訓練代碼中的這一行:
var environment = new CartPoleEnvironment().RLInit(maxStepsSoft: 1200, maxStepsHard: 1200);
這個看似普通的參數配置包含了在不讓GPU記憶體不堪重負的情況下進行非常長回合訓練的關鍵。讓我解釋:
當我們修改這些值時會發生什麼?
var environment = new CartPoleEnvironment().RLInit(maxStepsSoft: 200, maxStepsHard: 1200);
現在神奇的事情發生了:
- 我們只對前200步累積獎勵並計算梯度
- 模擬繼續自然運行到1200步或直到失敗
- GPU記憶體使用大幅下降
當您運行此配置時,查看您的獎勵圖表 – 您會注意到沒有獎勵超過200(我們的軟限制),儘管小車-桿物理模擬在該點之後仍在繼續。打開任務管理器,實時觀察記憶體節省情況。
這種技術對於回合可能無限運行的複雜環境變得不可或缺。與其因記憶體不足錯誤而崩潰,您可以精確控制投入多少計算努力,同時保持自然的環境動態。
觀察學習過程
當您運行此訓練時,會彈出一個顯示小車-桿環境的窗口。一開始,桿子會迅速倒下 – 您的智能體完全不知道該怎麼做。但在幾分鐘內,您將見證一個非凡的轉變:
- 最初,智能體做出隨機移動,沒有策略
- 然後它開始在桿子已經倒下時反應(太晚了!)
- 它逐漸學會更早做出糾正動作
- 最終,它做出微妙的預防性調整,使桿子保持完美平衡
這種可見的進展是什麼使小車-桿作為學習示例如此令人滿意。您不僅僅是看到圖表上的數字改善 – 您正在親眼目睹您的AI發展技能。
測試您的理解
理解小車-桿強化學習
下一步
在本教程中,您已經:
- 為強化學習設置了實時物理模擬
- 實現了一個完整的智能體來掌握經典控制問題
- 學習了如何使用軟/硬終止技巧高效管理記憶體
- 了解了RLMatrix的PPO實現與標準實現的不同之處
接下來,我們將不使用工具包實現相同的環境,讓您深入了解那些整潔屬性背後發生的事情。