AI時代系列(3) 機器學習三部曲: 📘 第三部:《強化學習 —— AI 的決策與進化》
59/100 第六週:📌 策略梯度與 Actor-Critic 架構
59. 實作練習:LunarLander with Actor-Critic 🌙 火箭著陸不是夢!
_______________________________________
🎯 單元目標
學會使用 Actor-Critic(演員-評論員)演算法 來解決經典強化學習環境 —— LunarLander-v2。
這是一個模擬太空船降落月球的挑戰,我們要讓火箭安全降落在地面,靠的是 AI 自己學會如何噴射推進器。
________________________________________
🧠 一、環境簡介:LunarLander-v2
• 狀態空間(State): 8 維連續值,包括座標、速度、角度與兩側著陸腳的接觸情況
• 動作空間(Action): 4 離散動作(不推、主引擎、左噴、右噴)
• 獎勵機制:
o 成功著陸:+100~140
o 摔壞機體:-100
o 維持平衡靠近中央、腳先著地也會給正獎勵
o 每用一次引擎會被懲罰(-0.03)
________________________________________
🧮 二、Actor-Critic 架構回顧
組件 功能描述
🎭 Actor 負責輸出「行動策略」π(s),給出某狀態下的行動機率分佈
🧾 Critic 負責估算「狀態價值」V(s),用來幫助 Actor 調整策略方向
🧩 損失函數 Actor 根據 TD 誤差更新策略,Critic 根據 TD 誤差更新價值
________________________________________
🔧 三、實作步驟與架構
🧱 1. 安裝環境
pip install gym[box2d] torch
🧠 2. 定義 Actor 和 Critic 網路
python
import torch
import torch.nn as nn
import torch.optim as optim
import gym
import numpy as np
env = gym.make("LunarLander-v2")
class Actor(nn.Module):
def __init__(self, input_dim, output_dim):
super().__init__()
self.model = nn.Sequential(
nn.Linear(input_dim, 128), nn.ReLU(),
nn.Linear(128, output_dim), nn.Softmax(dim=-1)
)
def forward(self, x):
return self.model(x)
class Critic(nn.Module):
def __init__(self, input_dim):
super().__init__()
self.model = nn.Sequential(
nn.Linear(input_dim, 128), nn.ReLU(),
nn.Linear(128, 1)
)
def forward(self, x):
return self.model(x)
這段程式定義了 Actor-Critic 架構 用於 LunarLander-v2 環境,其中 Actor 類別是一個策略網路,將輸入的狀態向量透過兩層全連接層(Linear + ReLU)轉換成動作機率分布(Softmax 輸出),學習策略 𝜋(𝑎∣𝑠);而 Critic 類別則是價值網路,透過類似的兩層結構,輸出狀態價值 𝑉(𝑠),用來評估當前狀態的長期回報,提供 Actor 更新時的基準參考(baseline)。
🔁 3. 互動與更新策略
python
actor = Actor(8, 4)
critic = Critic(8)
optimizerA = optim.Adam(actor.parameters(), lr=1e-3)
optimizerC = optim.Adam(critic.parameters(), lr=1e-3)
gamma = 0.99
for episode in range(1000):
state = env.reset()
episode_reward = 0
for t in range(1000):
state_tensor = torch.FloatTensor(state)
probs = actor(state_tensor)
dist = torch.distributions.Categorical(probs)
action = dist.sample()
next_state, reward, done, _ = env.step(action.item())
next_state_tensor = torch.FloatTensor(next_state)
# Critic 計算 TD 誤差
value = critic(state_tensor)
next_value = critic(next_state_tensor)
td_target = reward + gamma * next_value * (1 - int(done))
td_error = td_target - value
# 更新 Critic
critic_loss = td_error.pow(2)
optimizerC.zero_grad()
critic_loss.backward()
optimizerC.step()
# 更新 Actor(使用 TD 誤差作為優勢)
actor_loss = -dist.log_prob(action) * td_error.detach()
optimizerA.zero_grad()
actor_loss.backward()
optimizerA.step()
state = next_state
episode_reward += reward
if done:
break
print(f"Episode {episode} | Reward: {episode_reward}")
這段程式以 Actor-Critic 演算法訓練 LunarLander-v2,其中每回合透過 Actor 網路計算動作機率並抽樣執行,Critic 預測當前與下一狀態的價值,計算 TD 目標與 TD 誤差;Critic 使用 TD 誤差平方作為損失更新價值網路,Actor 則以 TD 誤差作為 Advantage,透過策略梯度公式 −log𝜋(𝑎∣𝑠)×TD誤差−logπ(a∣s) 反向更新策略網路,藉此穩定地提升整體行為策略,每回合完成後輸出累積回報。
________________________________________
📌 四、小技巧與調參建議
• 若學習不穩定,考慮加入 狀態正規化。
• 嘗試不同隱藏層大小,例如 64, 128, 256。
• 如果發現動作機率學不穩定,可以用 entropy bonus 來鼓勵探索。
• 想進一步優化,可升級為 Advantage Actor-Critic (A2C) 或 GAE(Generalized Advantage Estimation)。
________________________________________
🚀 五、總結
重點 說明
Actor 輸出策略 π(a s)
Critic 預測 V(s) 幫我們判斷當下做得好不好
TD 誤差 作為 Actor 和 Critic 同步學習的關鍵信號
火箭學會降落 🎯 強化學習真正從實驗中學習決策!