reinforcement learning
這裡利用 GridWorld 的遊戲來測試 Q-learning 的實作,
可以去作者 Github 下載 GridWorld Script
import wget
# 下載 Gridworld.py & GridBoard.py
wget.download("https://github.com/DeepReinforcementLearning/DeepReinforcementLearningInAction/raw/master/Errata/Gridworld.py")
wget.download("https://github.com/DeepReinforcementLearning/DeepReinforcementLearningInAction/raw/master/Errata/GridBoard.py")
遊戲是以下'棋盤'上進行,每次 Player 可以走一格,走到終點(+)為獲勝,陷阱(-)則是失敗
[['+',' ',' ','P'], # + : 終點
[' ','W',' ',' '], # - : 陷阱
[' ',' ',' ',' '], # P : player
[' ',' ','-',' ']] # W : 牆壁
# 走路指令 : 'u':往上, 'd':往下, 'l':往左, 'r':往右
遊戲模式 :
Reward 給予規則 :
遊戲狀態會以一個[3階四維]的陣列(Tensor)儲存,
四維的陣列分別是[玩家位置],[陷阱位置],[終點位置],[牆壁位置]
形成 ( 4 * 4 * 4 ) Shape 的陣列
ex: 玩家位置陣列
[[' ',' ',' ','P'],
[' ',' ',' ',' '],
[' ',' ',' ',' '],
[' ',' ',' ',' ']]
此遊戲有以下指令可以做操控
from Gridworld import Gridworld
# 建立一場遊戲
game = Gridworld( size=4, mode='static') # size:棋盤大小(4*4)
# 查看遊戲
game.display()
# 移動 Player
game.makeMove('u')
# 獲得 Reward
game.reward()
# 遊戲狀態 (state)
game.board.render_np()
Q-learning 理論公式可以看成以下幾個訓練元素
等於說要建一個 Q 函數的神經網路 model,利用來預測當前狀態各動作的價值,
並利用以上 Update 公式進行 Q model 權重的更新。
Q 函數會輸出該狀態各動作的期望價值,所以會有以下 input、output
input : 遊戲當前狀態,為 ( 4 * 4 * 4 ) 矩陣
output : 各動作價值,此遊戲有 4 種動作,輸出四個價值!
神經網路架構:
# 神經網路設定
layer1_size = 4*4*4
layer2_size = 150
layer3_size = 100
layer4_size = 4
model = nn.Sequential(
nn.Linear(in_features=layer1_size, out_features=layer2_size),
nn.ReLU(),
nn.Linear(layer2_size, layer3_size),
nn.ReLU(),
nn.Linear(layer3_size, layer4_size)
)
loss_fn = nn.MSELoss()
lr = 0.001
optimizer = torch.optim.Adam(model.parameters(), lr=lr)
# 折扣係數
gamma = 0.9
epsilon = 1 # epsilon-貪婪策略係數
到時候 output 會是各動作的期望價值,如果選擇了其中的動作,
會需要把 index 換成[動作指令],所以利用字典轉換
# 數字對應動作 (字典)
action_set = {
0:'u',
1:'d',
2:'l',
3:'r'
}
可以將訓練架構分為如下,前面 4 步驟(黃色格)就是為了計算 TD-Target,
之後就和 Q-learning Update 步驟相同,
特別說一下這次訓練是訓練 'static' 模式,所以是固定環境位置
from IPython.display import clear_output # 印出資訊使用(非必要)
epochs = 1000
losses = [] # 紀錄 loss(用來印出)
for i in range(epochs):
# 建立遊戲
game = Gridworld(size=4, mode='static')
# 獲得遊戲狀態 State
state_ = game.board.render_np().reshape(1,64) + np.random.rand(1,64)/10 # 將 shape(4*4*4) => 64,並加上雜訊
# 將當前狀態轉為 Tensor
state1 = torch.from_numpy(state_).float()
# 追蹤是否還繼續遊戲
status = 1 # 1:還在繼續
while(status == 1):
# ------------------------------ 當前預測 Q 值 ----------------------------------------
qval = model(state1) # 得到預測 Q
qval_ = qval.data.numpy() # 將預測值轉為 numpy 陣列
# ------------------------------ 選擇執行動作 (使用 epsilon-貪婪策略) ----------------------------------------
if(random.random() < epsilon):
action_ = np.random.randint(0,4) # 選擇隨機動作
else:
action_ = np.argmax(qval_) # 選擇最大動作(數字)
action = action_set[action_] # 數字轉換為對應動作
# ------------------------------ 執行動作、更新State、取得 Reward -----------------------------
# 執行動作
game.makeMove(action)
# 取得新狀態
state2_ = game.board.render_np().reshape(1,64) + np.random.rand(1,64)/10.0
state2 = torch.from_numpy(state2_).float()
# 取得 Reward
reward = game.reward()
# ------------------------------ 取得下一狀態最大 Q 值 --------------------------------------
# 預測下一狀態 Q (但不要產生運算圖)
with torch.no_grad():
newQ = model(state2.reshape(1,64))
# 取得最大 Q
maxQ = torch.max(newQ)
# ------------------------------ 計算 TD-Target(Y) -----------------------------------------
if(reward == -1):
Y = reward + ( gamma * maxQ )
else:
Y = reward # 遊戲已結束,無下一狀態,設 Y 為 reward
# ------------------------------ 獲得現在狀態 Q 值和 TD-target ------------------------------
Y = torch.Tensor([Y]).detach() # 分離此預測值網路(只更新預測 qval 的 model )
X = qval.squeeze()[action_] # 只取出預測執行的動作 Q,並去掉一階
# ------------------------------ 計算 loss (TD-ERROR) --------------------------------------
loss = loss_fn(X,Y)
# 印出資訊(每 100 epoch 印一次)
if( i%100 == 0 ):
print( i, loss.item() )
clear_output(wait = True)
# ------------------------------ Update 神經網路(Q function) ---------------------------------
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 將新狀態設為當前狀態
state1 = state2
if abs(reward) == 10:
status = 0 # 如遊戲結束 status 設為0
# 遞減 epsilon
if(epsilon > 0.1):
epsilon -= (1/epochs)
# 紀錄 loss
losses.append(loss.item())
訓練結果
plt.plot(losses)
plt.xlabel("Epoches", fontsize=11)
plt.ylabel("Loss", fontsize=11)
plt.show()
可以看到 Loss 明顯下降
定義以下函數來實測訓練的模型,架構與訓練有點像,但只需要 model 預測值
函數會回傳贏 or 輸,Display可以顯示遊戲過程
# 測試 model 玩遊戲
def test_model( model, mode='static', display=True):
i = 0
# 創建遊戲
test_game = Gridworld(size = 4, mode=mode)
# 當前狀態
state_ = test_game.board.render_np().reshape(1,64) + np.random.rand(1,64)/10.0
state = torch.from_numpy(state_).float()
if display:
print("Initial State:")
print(test_game.display())
status = 1
while(status == 1):
# 選擇動作
qval = model(state)
qval_ = qval.data.numpy()
action_ = np.argmax(qval_)
action = action_set[action_]
if display:
print(f"Move #: {i}; Taking action: {action}")
# 進行動作、更新當前狀態
test_game.makeMove(action)
state_ = test_game.board.render_np().reshape(1,64) + np.random.rand(1,64)/10.0
state = torch.from_numpy(state_).float()
if display:
print(test_game.display())
# 獲得 Reward,判斷輸贏
reward = test_game.reward()
if( reward != -1 ):
if reward > 0: # 贏了
status = 2
if display:
print(f"Game Won! Reward: {reward}")
else: # 輸了
status = 0
if display:
print(f"Game Lost! Reward: {reward}")
i += 1
if( i > 15 ):
if display:
print("Game Lost; too many moves.")
break
# 回傳輸贏結果
win = True if status == 2 else False
return win
實測模型
test_model( model, 'static',display=True)
但如果我們想要訓練 Random 環境 GridWorld 會發現此模型不可用
所以我將訓練步驟的遊戲模式改成 random ,但卻獲得不太好結果…
這是因為模型發生災難性失憶,會在下一篇講解。
一. 簡介 第二章有提到策略函數可以算出一狀態下,各動作的機率分佈。 我們事先不知道這個策略函數,需要先做策略近似,透過學習來近似策略函數, 而使用神經網路來近似策略函數的稱為策略網路。 <br> 二. 策略梯度法 :::success 策略梯度法 運作方式例子:有個100支籤的籤桶,每支籤有標動作編號,有4種動作(編號有可能是0~3),假設動作2有可能是最佳動作,籤筒內籤標為2的就較多,0、1、3就較少,抽重2號籤的機率最大,其餘仍有機會選中,讓演算法進行探索
Jun 15, 20252.1 多臂拉霸機問題 :::success 假設有10台拉霸機,每一台最高獎金為10美金,且它們的平均獎金是不同的,要如何選到平均獎金最高的拉霸機? ::: 策略:隨機選擇一台拉霸機並進行多輪遊戲,一輪遊戲拉一台拉霸一次,記錄每一輪獲得的獎金,計算每一台拉霸機的期望獎金(expected reward) :::warning 公式 $$ Q_k(a)=\frac{r(a1)+r(a2)+...+r(an)}{n} $$ $a$:拉霸機號碼 $Q_k(a)$:a拉霸在第K次遊戲中的期望獎金
Mar 6, 20251.強化學習介紹 :zap: 強化學習是機器學習中的一種策略,我們會設定要演算法達成的目標,然後根據演算法嘗試的結果給予回饋值 (達成目標給予正回饋、失敗則給負回饋) 直到能順利達成目標獲得正回饋為止。 2.強化學習架構 :zap: :arrow_right: 損失函數 Loss Function Loss Function 會給出一個值來評斷我們與目標的距離,當 Loss 越小就離目標越近。 :arrow_right: 環境 Environment & 狀態 State
Mar 6, 20251. 簡介 Actor-Critic 綜合了策略梯度法以及 Q-Learning 的特性, 會利用 [價值函數] 來評估 s 狀態的價值 (注意,這邊價值為狀態價值 $V_{\pi}$ ) 並利用 [策略函數] 輸出 s 狀態動作的分布機率來決定 action, 執行動作後,再利用得到的 Return 和剛預測的價值計算 "advantage" 來衡量動作好壞 可以把 actor critic 看成兩個神經網路,分別代表以下功能 : :clown_face: - Actor(演員) : 也就是 [策略函數],用來決定接下來的動作 :female-teacher: - Critic (評論家) : [價值函數] 用來評估狀態的價值
Aug 21, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up