Deep Reinforcement Learning Hands-On——Policy Gradients – an Alternative
作者:凱魯嘎吉 - 博客園 http://www.cnblogs.com/kailugaji/
更多請看:Reinforcement Learning - 隨筆分類 - 凱魯嘎吉 - 博客園 https://www.cnblogs.com/kailugaji/category/2038931.html
本文代碼下載:https://github.com/kailugaji/Hands-on-Reinforcement-Learning/tree/main/03%20Policy%20Gradients
這一篇博文參考了書目《Deep Reinforcement Learning Hands-On Second Edition》第11章內容,主要介紹基於策略函數的強化學習方法,包括:REINFORCE、帶基准線的REINFORCE算法(REINFORCE with Baseline)以及策略梯度方法(引入entropy bonus來增加探索,引入基准線來解決方差大訓練不穩定問題)。具體理論知識,請參見:強化學習(Reinforcement Learning) - 凱魯嘎吉 - 博客園。為了與DQN算法作對比,首先用Python重新實現了DQN算法(架構不是標准的三卷積兩全連接,而是簡化為兩全連接) 01_cartpole_dqn.py,接着分別實現基於策略函數的三個強化學習方法02_cartpole_reinforce.py,03_cartpole_reinforce_baseline.py,與04_cartpole_pg.py,還有一個改進的策略梯度算法見:https://github.com/kailugaji/Hands-on-Reinforcement-Learning/blob/main/03%20Policy%20Gradients/05_pong_pg.py,該算法用到了梯度裁剪策略,多環境並行實現,采用移動平均法定義基准線,由於某些外在因素,結果並未列出,可自行運行。06_cartpole_pg.py是04_cartpole_pg.py的擴展,唯一的區別在於baseline可以由用戶選擇加或者不加,建議使用06_cartpole_pg.py。
值函數與策略函數方法的區別:基於值函數的方法網絡輸出的是Q值,而基於策略函數的方法網絡輸出的是動作的概率分布(代碼里是輸出Q值,再進行softmax得到概率分布),通過隨機采樣,得到最終的動作。
1. 01_cartpole_dqn.py
1.1 程序
#!/usr/bin/env python3
# -*- coding=utf-8 -*-
# DQN
# The CartPole example
# https://www.cnblogs.com/kailugaji/
import gym
import ptan
import numpy as np
from tensorboardX import SummaryWriter
import torch
import torch.nn as nn
import torch.optim as optim
GAMMA = 0.99 # 折扣率 0.9
LEARNING_RATE = 0.01 # 學習率 5e-3
BATCH_SIZE = 16 # 一批xx個樣本 16
EPSILON_START = 1.0 # epsilon因子
EPSILON_STOP = 0.02
EPSILON_STEPS = 5000
REPLAY_BUFFER = 5000 # 經驗回放池容量
# 構建網絡
class DQN(nn.Module):
def __init__(self, input_size, n_actions):
# input_size:輸入狀態維度,hidden_size:隱層維度=128,n_actions:輸出動作維度
super(DQN, self).__init__()
self.net = nn.Sequential(
nn.Linear(input_size, 128), # 全連接層,隱層預設為128維度
nn.ReLU(),
nn.Linear(128, n_actions) # 全連接層
)
def forward(self, x):
return self.net(x)
# 目標網絡 r + gamma * max Q(s, a)
def calc_target(net, local_reward, next_state):
if next_state is None:
return local_reward
state_v = torch.tensor([next_state], dtype=torch.float32)
next_q_v = net(state_v) # 將最后的狀態輸入網絡,得到Q(s, a)
best_q = next_q_v.max(dim=1)[0].item() # 找最大的Q
return local_reward + GAMMA * best_q
# r + gamma * max Q(s, a)
if __name__ == "__main__":
env = gym.make("CartPole-v0") # 創建游戲環境
writer = SummaryWriter(comment="-cartpole-dqn")
net = DQN(env.observation_space.shape[0], env.action_space.n) # 4(狀態)->128->2(動作)
# print(net)
selector = ptan.actions.EpsilonGreedyActionSelector(epsilon=EPSILON_START)
# epsilon-greedy action selector,初始epsilon=1
agent = ptan.agent.DQNAgent(net, selector, preprocessor=ptan.agent.float32_preprocessor)
# DQNAgent:離散
# dqn_model換成自定義的DQN模型,4(狀態)->128->2(動作)
exp_source = ptan.experience.ExperienceSourceFirstLast(env, agent, gamma=GAMMA)
# 返回運行記錄以用於訓練模型,輸出格式為:(state, action, reward, last_state)
replay_buffer = ptan.experience.ExperienceReplayBuffer(exp_source, REPLAY_BUFFER)
# 經驗回放池,構建buffer,容量為1000,當前沒東西,len(buffer) = 0
optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE) # Adam優化
mse_loss = nn.MSELoss() # MSE loss
total_rewards = [] # the total rewards for the episodes
step_idx = 0 # 迭代次數/輪數
done_episodes = 0 # 局數,幾局游戲
while True:
step_idx += 1
selector.epsilon = max(EPSILON_STOP, EPSILON_START - step_idx / EPSILON_STEPS)
# epsilon隨迭代步數的衰減策略
replay_buffer.populate(1) # 從環境中獲取一個新樣本
if len(replay_buffer) < BATCH_SIZE: # buffer里面還沒超過BATCH_SIZE個樣本
continue
# sample batch
batch = replay_buffer.sample(BATCH_SIZE) # 從buffer里面均勻抽樣一個批次的樣本,一批BATCH_SIZE個樣本
batch_states = [exp.state for exp in batch]
batch_actions = [exp.action for exp in batch]
batch_targets = [calc_target(net, exp.reward, exp.last_state)
for exp in batch] # r + gamma * max Q(s, a)
# train
optimizer.zero_grad()
states_v = torch.FloatTensor(batch_states)
net_q_v = net(states_v) # 輸入狀態,輸出Q(s, a)值
target_q = net_q_v.data.numpy().copy() # copy網絡參數
target_q[range(BATCH_SIZE), batch_actions] = batch_targets
target_q_v = torch.tensor(target_q) # r + gamma * max Q(s, a)
loss_v = mse_loss(net_q_v, target_q_v) # min L = (r + gamma * max Q(s', a') - Q(s, a))^2
loss_v.backward()
optimizer.step()
# handle new rewards
new_rewards = exp_source.pop_total_rewards() # 返回一局游戲過后的total_rewords
if new_rewards:
done_episodes += 1
reward = new_rewards[0]
total_rewards.append(reward) # 前done_episodes局游戲的獎勵之和
mean_rewards = float(np.mean(total_rewards[-100:])) # total_rewards/done_episodes
print("第%d次: 第%d局游戲結束, 獎勵為%6.2f, 平均獎勵為%6.2f, epsilon為%.2f" % (step_idx, done_episodes, reward, mean_rewards, selector.epsilon))
writer.add_scalar("reward", reward, step_idx)
writer.add_scalar("reward_100", mean_rewards, step_idx)
writer.add_scalar("epsilon", selector.epsilon, step_idx)
writer.add_scalar("episodes", done_episodes, step_idx)
if mean_rewards > 50: # 最大期望獎勵閾值,只有當平均獎勵 > 50時才結束游戲
print("經過%d輪完成%d局游戲!" % (step_idx, done_episodes))
break
writer.close()
1.2 結果
第17次: 第1局游戲結束, 獎勵為 16.00, 平均獎勵為 16.00, epsilon為1.00
第40次: 第2局游戲結束, 獎勵為 23.00, 平均獎勵為 19.50, epsilon為0.99
第67次: 第3局游戲結束, 獎勵為 27.00, 平均獎勵為 22.00, epsilon為0.99
第105次: 第4局游戲結束, 獎勵為 38.00, 平均獎勵為 26.00, epsilon為0.98
第142次: 第5局游戲結束, 獎勵為 37.00, 平均獎勵為 28.20, epsilon為0.97
第161次: 第6局游戲結束, 獎勵為 19.00, 平均獎勵為 26.67, epsilon為0.97
第186次: 第7局游戲結束, 獎勵為 25.00, 平均獎勵為 26.43, epsilon為0.96
第197次: 第8局游戲結束, 獎勵為 11.00, 平均獎勵為 24.50, epsilon為0.96
第219次: 第9局游戲結束, 獎勵為 22.00, 平均獎勵為 24.22, epsilon為0.96
第249次: 第10局游戲結束, 獎勵為 30.00, 平均獎勵為 24.80, epsilon為0.95
第262次: 第11局游戲結束, 獎勵為 13.00, 平均獎勵為 23.73, epsilon為0.95
第283次: 第12局游戲結束, 獎勵為 21.00, 平均獎勵為 23.50, epsilon為0.94
第307次: 第13局游戲結束, 獎勵為 24.00, 平均獎勵為 23.54, epsilon為0.94
第333次: 第14局游戲結束, 獎勵為 26.00, 平均獎勵為 23.71, epsilon為0.93
第348次: 第15局游戲結束, 獎勵為 15.00, 平均獎勵為 23.13, epsilon為0.93
第387次: 第16局游戲結束, 獎勵為 39.00, 平均獎勵為 24.12, epsilon為0.92
第411次: 第17局游戲結束, 獎勵為 24.00, 平均獎勵為 24.12, epsilon為0.92
第429次: 第18局游戲結束, 獎勵為 18.00, 平均獎勵為 23.78, epsilon為0.91
第469次: 第19局游戲結束, 獎勵為 40.00, 平均獎勵為 24.63, epsilon為0.91
第481次: 第20局游戲結束, 獎勵為 12.00, 平均獎勵為 24.00, epsilon為0.90
第493次: 第21局游戲結束, 獎勵為 12.00, 平均獎勵為 23.43, epsilon為0.90
第513次: 第22局游戲結束, 獎勵為 20.00, 平均獎勵為 23.27, epsilon為0.90
第527次: 第23局游戲結束, 獎勵為 14.00, 平均獎勵為 22.87, epsilon為0.89
第578次: 第24局游戲結束, 獎勵為 51.00, 平均獎勵為 24.04, epsilon為0.88
第592次: 第25局游戲結束, 獎勵為 14.00, 平均獎勵為 23.64, epsilon為0.88
第604次: 第26局游戲結束, 獎勵為 12.00, 平均獎勵為 23.19, epsilon為0.88
第632次: 第27局游戲結束, 獎勵為 28.00, 平均獎勵為 23.37, epsilon為0.87
第664次: 第28局游戲結束, 獎勵為 32.00, 平均獎勵為 23.68, epsilon為0.87
第700次: 第29局游戲結束, 獎勵為 36.00, 平均獎勵為 24.10, epsilon為0.86
第711次: 第30局游戲結束, 獎勵為 11.00, 平均獎勵為 23.67, epsilon為0.86
第745次: 第31局游戲結束, 獎勵為 34.00, 平均獎勵為 24.00, epsilon為0.85
第760次: 第32局游戲結束, 獎勵為 15.00, 平均獎勵為 23.72, epsilon為0.85
第774次: 第33局游戲結束, 獎勵為 14.00, 平均獎勵為 23.42, epsilon為0.85
第798次: 第34局游戲結束, 獎勵為 24.00, 平均獎勵為 23.44, epsilon為0.84
第817次: 第35局游戲結束, 獎勵為 19.00, 平均獎勵為 23.31, epsilon為0.84
第829次: 第36局游戲結束, 獎勵為 12.00, 平均獎勵為 23.00, epsilon為0.83
第862次: 第37局游戲結束, 獎勵為 33.00, 平均獎勵為 23.27, epsilon為0.83
第881次: 第38局游戲結束, 獎勵為 19.00, 平均獎勵為 23.16, epsilon為0.82
第906次: 第39局游戲結束, 獎勵為 25.00, 平均獎勵為 23.21, epsilon為0.82
第929次: 第40局游戲結束, 獎勵為 23.00, 平均獎勵為 23.20, epsilon為0.81
第963次: 第41局游戲結束, 獎勵為 34.00, 平均獎勵為 23.46, epsilon為0.81
第987次: 第42局游戲結束, 獎勵為 24.00, 平均獎勵為 23.48, epsilon為0.80
第1017次: 第43局游戲結束, 獎勵為 30.00, 平均獎勵為 23.63, epsilon為0.80
第1062次: 第44局游戲結束, 獎勵為 45.00, 平均獎勵為 24.11, epsilon為0.79
第1131次: 第45局游戲結束, 獎勵為 69.00, 平均獎勵為 25.11, epsilon為0.77
第1163次: 第46局游戲結束, 獎勵為 32.00, 平均獎勵為 25.26, epsilon為0.77
第1173次: 第47局游戲結束, 獎勵為 10.00, 平均獎勵為 24.94, epsilon為0.77
第1190次: 第48局游戲結束, 獎勵為 17.00, 平均獎勵為 24.77, epsilon為0.76
第1222次: 第49局游戲結束, 獎勵為 32.00, 平均獎勵為 24.92, epsilon為0.76
第1243次: 第50局游戲結束, 獎勵為 21.00, 平均獎勵為 24.84, epsilon為0.75
第1265次: 第51局游戲結束, 獎勵為 22.00, 平均獎勵為 24.78, epsilon為0.75
第1277次: 第52局游戲結束, 獎勵為 12.00, 平均獎勵為 24.54, epsilon為0.74
第1292次: 第53局游戲結束, 獎勵為 15.00, 平均獎勵為 24.36, epsilon為0.74
第1325次: 第54局游戲結束, 獎勵為 33.00, 平均獎勵為 24.52, epsilon為0.73
第1341次: 第55局游戲結束, 獎勵為 16.00, 平均獎勵為 24.36, epsilon為0.73
第1370次: 第56局游戲結束, 獎勵為 29.00, 平均獎勵為 24.45, epsilon為0.73
第1403次: 第57局游戲結束, 獎勵為 33.00, 平均獎勵為 24.60, epsilon為0.72
第1422次: 第58局游戲結束, 獎勵為 19.00, 平均獎勵為 24.50, epsilon為0.72
第1471次: 第59局游戲結束, 獎勵為 49.00, 平均獎勵為 24.92, epsilon為0.71
第1483次: 第60局游戲結束, 獎勵為 12.00, 平均獎勵為 24.70, epsilon為0.70
第1594次: 第61局游戲結束, 獎勵為111.00, 平均獎勵為 26.11, epsilon為0.68
第1621次: 第62局游戲結束, 獎勵為 27.00, 平均獎勵為 26.13, epsilon為0.68
第1637次: 第63局游戲結束, 獎勵為 16.00, 平均獎勵為 25.97, epsilon為0.67
第1684次: 第64局游戲結束, 獎勵為 47.00, 平均獎勵為 26.30, epsilon為0.66
第1805次: 第65局游戲結束, 獎勵為121.00, 平均獎勵為 27.75, epsilon為0.64
第1855次: 第66局游戲結束, 獎勵為 50.00, 平均獎勵為 28.09, epsilon為0.63
第1904次: 第67局游戲結束, 獎勵為 49.00, 平均獎勵為 28.40, epsilon為0.62
第1924次: 第68局游戲結束, 獎勵為 20.00, 平均獎勵為 28.28, epsilon為0.62
第1967次: 第69局游戲結束, 獎勵為 43.00, 平均獎勵為 28.49, epsilon為0.61
第2042次: 第70局游戲結束, 獎勵為 75.00, 平均獎勵為 29.16, epsilon為0.59
第2075次: 第71局游戲結束, 獎勵為 33.00, 平均獎勵為 29.21, epsilon為0.58
第2110次: 第72局游戲結束, 獎勵為 35.00, 平均獎勵為 29.29, epsilon為0.58
第2127次: 第73局游戲結束, 獎勵為 17.00, 平均獎勵為 29.12, epsilon為0.57
第2161次: 第74局游戲結束, 獎勵為 34.00, 平均獎勵為 29.19, epsilon為0.57
第2219次: 第75局游戲結束, 獎勵為 58.00, 平均獎勵為 29.57, epsilon為0.56
第2238次: 第76局游戲結束, 獎勵為 19.00, 平均獎勵為 29.43, epsilon為0.55
第2300次: 第77局游戲結束, 獎勵為 62.00, 平均獎勵為 29.86, epsilon為0.54
第2348次: 第78局游戲結束, 獎勵為 48.00, 平均獎勵為 30.09, epsilon為0.53
第2454次: 第79局游戲結束, 獎勵為106.00, 平均獎勵為 31.05, epsilon為0.51
第2527次: 第80局游戲結束, 獎勵為 73.00, 平均獎勵為 31.57, epsilon為0.49
第2590次: 第81局游戲結束, 獎勵為 63.00, 平均獎勵為 31.96, epsilon為0.48
第2642次: 第82局游戲結束, 獎勵為 52.00, 平均獎勵為 32.21, epsilon為0.47
第2723次: 第83局游戲結束, 獎勵為 81.00, 平均獎勵為 32.80, epsilon為0.46
第2824次: 第84局游戲結束, 獎勵為101.00, 平均獎勵為 33.61, epsilon為0.44
第2865次: 第85局游戲結束, 獎勵為 41.00, 平均獎勵為 33.69, epsilon為0.43
第2957次: 第86局游戲結束, 獎勵為 92.00, 平均獎勵為 34.37, epsilon為0.41
第3067次: 第87局游戲結束, 獎勵為110.00, 平均獎勵為 35.24, epsilon為0.39
第3124次: 第88局游戲結束, 獎勵為 57.00, 平均獎勵為 35.49, epsilon為0.38
第3188次: 第89局游戲結束, 獎勵為 64.00, 平均獎勵為 35.81, epsilon為0.36
第3274次: 第90局游戲結束, 獎勵為 86.00, 平均獎勵為 36.37, epsilon為0.35
第3334次: 第91局游戲結束, 獎勵為 60.00, 平均獎勵為 36.63, epsilon為0.33
第3424次: 第92局游戲結束, 獎勵為 90.00, 平均獎勵為 37.21, epsilon為0.32
第3503次: 第93局游戲結束, 獎勵為 79.00, 平均獎勵為 37.66, epsilon為0.30
第3587次: 第94局游戲結束, 獎勵為 84.00, 平均獎勵為 38.15, epsilon為0.28
第3787次: 第95局游戲結束, 獎勵為200.00, 平均獎勵為 39.85, epsilon為0.24
第3879次: 第96局游戲結束, 獎勵為 92.00, 平均獎勵為 40.40, epsilon為0.22
第3965次: 第97局游戲結束, 獎勵為 86.00, 平均獎勵為 40.87, epsilon為0.21
第4070次: 第98局游戲結束, 獎勵為105.00, 平均獎勵為 41.52, epsilon為0.19
第4146次: 第99局游戲結束, 獎勵為 76.00, 平均獎勵為 41.87, epsilon為0.17
第4199次: 第100局游戲結束, 獎勵為 53.00, 平均獎勵為 41.98, epsilon為0.16
第4250次: 第101局游戲結束, 獎勵為 51.00, 平均獎勵為 42.33, epsilon為0.15
第4321次: 第102局游戲結束, 獎勵為 71.00, 平均獎勵為 42.81, epsilon為0.14
第4418次: 第103局游戲結束, 獎勵為 97.00, 平均獎勵為 43.51, epsilon為0.12
第4537次: 第104局游戲結束, 獎勵為119.00, 平均獎勵為 44.32, epsilon為0.09
第4680次: 第105局游戲結束, 獎勵為143.00, 平均獎勵為 45.38, epsilon為0.06
第4749次: 第106局游戲結束, 獎勵為 69.00, 平均獎勵為 45.88, epsilon為0.05
第4888次: 第107局游戲結束, 獎勵為139.00, 平均獎勵為 47.02, epsilon為0.02
第4941次: 第108局游戲結束, 獎勵為 53.00, 平均獎勵為 47.44, epsilon為0.02
第5106次: 第109局游戲結束, 獎勵為165.00, 平均獎勵為 48.87, epsilon為0.02
第5162次: 第110局游戲結束, 獎勵為 56.00, 平均獎勵為 49.13, epsilon為0.02
第5212次: 第111局游戲結束, 獎勵為 50.00, 平均獎勵為 49.50, epsilon為0.02
第5286次: 第112局游戲結束, 獎勵為 74.00, 平均獎勵為 50.03, epsilon為0.02
經過5286輪完成112局游戲!
epsilon衰減曲線
2. 02_cartpole_reinforce.py
2.1 程序
#!/usr/bin/env python3
# -*- coding=utf-8 -*-
# Policy Gradients——REINFORCE
# The CartPole example
# https://www.cnblogs.com/kailugaji/
import gym
import ptan
import numpy as np
from tensorboardX import SummaryWriter
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
GAMMA = 0.99 # 折扣率
LEARNING_RATE = 0.01 # 學習率
EPISODES_TO_TRAIN = 4 # how many complete episodes we will use for training
# 構建網絡
class PGN(nn.Module):
def __init__(self, input_size, n_actions):
# input_size:輸入狀態維度,hidden_size:隱層維度=128,n_actions:輸出動作維度
super(PGN, self).__init__()
self.net = nn.Sequential(
nn.Linear(input_size, 128), # 全連接層,隱層預設為128維度
nn.ReLU(),
nn.Linear(128, n_actions) # 全連接層
)
def forward(self, x):
return self.net(x) # 未用softmax
# Calculate the reward from the end of the local reward list.
# Indeed, the last step of the episode will have a total reward equal to its local reward.
# The step before the last will have the total reward of r(𝑡−1) + gamma * r(𝑡)
# sum(gamma^t * reward)
def calc_qvals(rewards):
res = []
sum_r = 0.0
for r in reversed(rewards): # reversed: 返回反向的迭代器對象
sum_r *= GAMMA # gamma * r(𝑡), r(t): the total reward for the previous steps
sum_r += r # r(𝑡−1) + gamma * r(𝑡), r(t-1): the local reward
res.append(sum_r) # the discounted total reward
return list(reversed(res)) # a list of rewards for the whole episode
if __name__ == "__main__":
env = gym.make("CartPole-v0") # 創建游戲環境
writer = SummaryWriter(comment="-cartpole-reinforce")
net = PGN(env.observation_space.shape[0], env.action_space.n) # 4(狀態)->128->2(動作)
# print(net)
agent = ptan.agent.PolicyAgent(net, preprocessor=ptan.agent.float32_preprocessor, apply_softmax=True)
# PolicyAgent:連續
# make a decision about actions for every observation (依概率)
# apply_softmax=True:網絡輸出先經過softmax轉化成概率,再從這個概率分布中進行隨機抽樣
# float32_preprocessor:returns the observation as float64 instead of the float32 required by PyTorch
exp_source = ptan.experience.ExperienceSourceFirstLast(env, agent, gamma=GAMMA)
# 返回運行記錄以用於訓練模型,輸出格式為:(state, action, reward, last_state)
optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE) # Adam優化
total_rewards = [] # the total rewards for the episodes
step_idx = 0 # 迭代次數/輪數
done_episodes = 0 # 局數,幾局游戲
batch_episodes = 0
batch_states, batch_actions, batch_qvals = [], [], []
cur_rewards = [] # local rewards for the episode being currently played
for step_idx, exp in enumerate(exp_source): # (state, action, reward, last_state)
batch_states.append(exp.state) # 狀態
batch_actions.append(int(exp.action)) # 動作
cur_rewards.append(exp.reward) # 即時獎勵
if exp.last_state is None: # 一局游戲結束
batch_qvals.extend(calc_qvals(cur_rewards)) # the discounted total rewards
cur_rewards.clear()
batch_episodes += 1
# handle new rewards
new_rewards = exp_source.pop_total_rewards() # 返回一局游戲過后的total_rewords
if new_rewards:
done_episodes += 1 # 游戲局數(回合數)
reward = new_rewards[0]
total_rewards.append(reward) # the total rewards for the episodes
mean_rewards = float(np.mean(total_rewards[-100:])) # 平均獎勵
print("第%d次: 第%d局游戲結束, 獎勵為%6.2f, 平均獎勵為%6.2f" % (step_idx, done_episodes, reward, mean_rewards))
writer.add_scalar("reward", reward, step_idx)
writer.add_scalar("reward_100", mean_rewards, step_idx)
writer.add_scalar("episodes", done_episodes, step_idx)
if mean_rewards > 50: # 最大期望獎勵閾值,只有當mean_rewards > 50時才結束游戲
print("經過%d輪完成%d局游戲!" % (step_idx, done_episodes))
break
if batch_episodes < EPISODES_TO_TRAIN: # how many complete episodes we will use for training
continue
# train
optimizer.zero_grad()
states_v = torch.FloatTensor(batch_states)
batch_actions_t = torch.LongTensor(batch_actions)
batch_qvals_v = torch.FloatTensor(batch_qvals) # the discounted batch total rewards
logits_v = net(states_v) # 輸入狀態,輸出Q(s, a)值
log_prob_v = F.log_softmax(logits_v, dim=1) # 輸出動作的對數概率分布 log π(s, a)
log_prob_actions_v = batch_qvals_v * log_prob_v[range(len(batch_states)), batch_actions_t]
# max sum(gamma^t * reward) * log π(s, a)
loss_v = -log_prob_actions_v.mean() # min
loss_v.backward()
optimizer.step()
batch_episodes = 0
batch_states.clear()
batch_actions.clear()
batch_qvals.clear()
writer.close()
2.2 結果
第21次: 第1局游戲結束, 獎勵為 21.00, 平均獎勵為 21.00
第65次: 第2局游戲結束, 獎勵為 44.00, 平均獎勵為 32.50
第78次: 第3局游戲結束, 獎勵為 13.00, 平均獎勵為 26.00
第91次: 第4局游戲結束, 獎勵為 13.00, 平均獎勵為 22.75
第112次: 第5局游戲結束, 獎勵為 21.00, 平均獎勵為 22.40
第131次: 第6局游戲結束, 獎勵為 19.00, 平均獎勵為 21.83
第158次: 第7局游戲結束, 獎勵為 27.00, 平均獎勵為 22.57
第173次: 第8局游戲結束, 獎勵為 15.00, 平均獎勵為 21.62
第199次: 第9局游戲結束, 獎勵為 26.00, 平均獎勵為 22.11
第212次: 第10局游戲結束, 獎勵為 13.00, 平均獎勵為 21.20
第240次: 第11局游戲結束, 獎勵為 28.00, 平均獎勵為 21.82
第267次: 第12局游戲結束, 獎勵為 27.00, 平均獎勵為 22.25
第289次: 第13局游戲結束, 獎勵為 22.00, 平均獎勵為 22.23
第310次: 第14局游戲結束, 獎勵為 21.00, 平均獎勵為 22.14
第335次: 第15局游戲結束, 獎勵為 25.00, 平均獎勵為 22.33
第377次: 第16局游戲結束, 獎勵為 42.00, 平均獎勵為 23.56
第386次: 第17局游戲結束, 獎勵為 9.00, 平均獎勵為 22.71
第442次: 第18局游戲結束, 獎勵為 56.00, 平均獎勵為 24.56
第463次: 第19局游戲結束, 獎勵為 21.00, 平均獎勵為 24.37
第510次: 第20局游戲結束, 獎勵為 47.00, 平均獎勵為 25.50
第572次: 第21局游戲結束, 獎勵為 62.00, 平均獎勵為 27.24
第627次: 第22局游戲結束, 獎勵為 55.00, 平均獎勵為 28.50
第671次: 第23局游戲結束, 獎勵為 44.00, 平均獎勵為 29.17
第761次: 第24局游戲結束, 獎勵為 90.00, 平均獎勵為 31.71
第797次: 第25局游戲結束, 獎勵為 36.00, 平均獎勵為 31.88
第873次: 第26局游戲結束, 獎勵為 76.00, 平均獎勵為 33.58
第932次: 第27局游戲結束, 獎勵為 59.00, 平均獎勵為 34.52
第965次: 第28局游戲結束, 獎勵為 33.00, 平均獎勵為 34.46
第1017次: 第29局游戲結束, 獎勵為 52.00, 平均獎勵為 35.07
第1047次: 第30局游戲結束, 獎勵為 30.00, 平均獎勵為 34.90
第1121次: 第31局游戲結束, 獎勵為 74.00, 平均獎勵為 36.16
第1139次: 第32局游戲結束, 獎勵為 18.00, 平均獎勵為 35.59
第1161次: 第33局游戲結束, 獎勵為 22.00, 平均獎勵為 35.18
第1329次: 第34局游戲結束, 獎勵為168.00, 平均獎勵為 39.09
第1361次: 第35局游戲結束, 獎勵為 32.00, 平均獎勵為 38.89
第1414次: 第36局游戲結束, 獎勵為 53.00, 平均獎勵為 39.28
第1431次: 第37局游戲結束, 獎勵為 17.00, 平均獎勵為 38.68
第1519次: 第38局游戲結束, 獎勵為 88.00, 平均獎勵為 39.97
第1552次: 第39局游戲結束, 獎勵為 33.00, 平均獎勵為 39.79
第1568次: 第40局游戲結束, 獎勵為 16.00, 平均獎勵為 39.20
第1614次: 第41局游戲結束, 獎勵為 46.00, 平均獎勵為 39.37
第1674次: 第42局游戲結束, 獎勵為 60.00, 平均獎勵為 39.86
第1750次: 第43局游戲結束, 獎勵為 76.00, 平均獎勵為 40.70
第1802次: 第44局游戲結束, 獎勵為 52.00, 平均獎勵為 40.95
第1854次: 第45局游戲結束, 獎勵為 52.00, 平均獎勵為 41.20
第1897次: 第46局游戲結束, 獎勵為 43.00, 平均獎勵為 41.24
第1994次: 第47局游戲結束, 獎勵為 97.00, 平均獎勵為 42.43
第2051次: 第48局游戲結束, 獎勵為 57.00, 平均獎勵為 42.73
第2105次: 第49局游戲結束, 獎勵為 54.00, 平均獎勵為 42.96
第2169次: 第50局游戲結束, 獎勵為 64.00, 平均獎勵為 43.38
第2202次: 第51局游戲結束, 獎勵為 33.00, 平均獎勵為 43.18
第2220次: 第52局游戲結束, 獎勵為 18.00, 平均獎勵為 42.69
第2254次: 第53局游戲結束, 獎勵為 34.00, 平均獎勵為 42.53
第2310次: 第54局游戲結束, 獎勵為 56.00, 平均獎勵為 42.78
第2367次: 第55局游戲結束, 獎勵為 57.00, 平均獎勵為 43.04
第2450次: 第56局游戲結束, 獎勵為 83.00, 平均獎勵為 43.75
第2496次: 第57局游戲結束, 獎勵為 46.00, 平均獎勵為 43.79
第2532次: 第58局游戲結束, 獎勵為 36.00, 平均獎勵為 43.66
第2554次: 第59局游戲結束, 獎勵為 22.00, 平均獎勵為 43.29
第2599次: 第60局游戲結束, 獎勵為 45.00, 平均獎勵為 43.32
第2630次: 第61局游戲結束, 獎勵為 31.00, 平均獎勵為 43.11
第2659次: 第62局游戲結束, 獎勵為 29.00, 平均獎勵為 42.89
第2708次: 第63局游戲結束, 獎勵為 49.00, 平均獎勵為 42.98
第2772次: 第64局游戲結束, 獎勵為 64.00, 平均獎勵為 43.31
第2801次: 第65局游戲結束, 獎勵為 29.00, 平均獎勵為 43.09
第2830次: 第66局游戲結束, 獎勵為 29.00, 平均獎勵為 42.88
第2878次: 第67局游戲結束, 獎勵為 48.00, 平均獎勵為 42.96
第2928次: 第68局游戲結束, 獎勵為 50.00, 平均獎勵為 43.06
第2947次: 第69局游戲結束, 獎勵為 19.00, 平均獎勵為 42.71
第2973次: 第70局游戲結束, 獎勵為 26.00, 平均獎勵為 42.47
第3004次: 第71局游戲結束, 獎勵為 31.00, 平均獎勵為 42.31
第3050次: 第72局游戲結束, 獎勵為 46.00, 平均獎勵為 42.36
第3073次: 第73局游戲結束, 獎勵為 23.00, 平均獎勵為 42.10
第3149次: 第74局游戲結束, 獎勵為 76.00, 平均獎勵為 42.55
第3193次: 第75局游戲結束, 獎勵為 44.00, 平均獎勵為 42.57
第3216次: 第76局游戲結束, 獎勵為 23.00, 平均獎勵為 42.32
第3272次: 第77局游戲結束, 獎勵為 56.00, 平均獎勵為 42.49
第3327次: 第78局游戲結束, 獎勵為 55.00, 平均獎勵為 42.65
第3401次: 第79局游戲結束, 獎勵為 74.00, 平均獎勵為 43.05
第3457次: 第80局游戲結束, 獎勵為 56.00, 平均獎勵為 43.21
第3486次: 第81局游戲結束, 獎勵為 29.00, 平均獎勵為 43.04
第3531次: 第82局游戲結束, 獎勵為 45.00, 平均獎勵為 43.06
第3583次: 第83局游戲結束, 獎勵為 52.00, 平均獎勵為 43.17
第3600次: 第84局游戲結束, 獎勵為 17.00, 平均獎勵為 42.86
第3661次: 第85局游戲結束, 獎勵為 61.00, 平均獎勵為 43.07
第3688次: 第86局游戲結束, 獎勵為 27.00, 平均獎勵為 42.88
第3751次: 第87局游戲結束, 獎勵為 63.00, 平均獎勵為 43.11
第3825次: 第88局游戲結束, 獎勵為 74.00, 平均獎勵為 43.47
第3973次: 第89局游戲結束, 獎勵為148.00, 平均獎勵為 44.64
第4033次: 第90局游戲結束, 獎勵為 60.00, 平均獎勵為 44.81
第4103次: 第91局游戲結束, 獎勵為 70.00, 平均獎勵為 45.09
第4160次: 第92局游戲結束, 獎勵為 57.00, 平均獎勵為 45.22
第4192次: 第93局游戲結束, 獎勵為 32.00, 平均獎勵為 45.08
第4255次: 第94局游戲結束, 獎勵為 63.00, 平均獎勵為 45.27
第4326次: 第95局游戲結束, 獎勵為 71.00, 平均獎勵為 45.54
第4397次: 第96局游戲結束, 獎勵為 71.00, 平均獎勵為 45.80
第4453次: 第97局游戲結束, 獎勵為 56.00, 平均獎勵為 45.91
第4483次: 第98局游戲結束, 獎勵為 30.00, 平均獎勵為 45.74
第4521次: 第99局游戲結束, 獎勵為 38.00, 平均獎勵為 45.67
第4608次: 第100局游戲結束, 獎勵為 87.00, 平均獎勵為 46.08
第4690次: 第101局游戲結束, 獎勵為 82.00, 平均獎勵為 46.69
第4737次: 第102局游戲結束, 獎勵為 47.00, 平均獎勵為 46.72
第4801次: 第103局游戲結束, 獎勵為 64.00, 平均獎勵為 47.23
第4893次: 第104局游戲結束, 獎勵為 92.00, 平均獎勵為 48.02
第4981次: 第105局游戲結束, 獎勵為 88.00, 平均獎勵為 48.69
第5038次: 第106局游戲結束, 獎勵為 57.00, 平均獎勵為 49.07
第5109次: 第107局游戲結束, 獎勵為 71.00, 平均獎勵為 49.51
第5138次: 第108局游戲結束, 獎勵為 29.00, 平均獎勵為 49.65
第5189次: 第109局游戲結束, 獎勵為 51.00, 平均獎勵為 49.90
第5278次: 第110局游戲結束, 獎勵為 89.00, 平均獎勵為 50.66
經過5278輪完成110局游戲!
3. 03_cartpole_reinforce_baseline.py
3.1 程序
#!/usr/bin/env python3
# -*- coding=utf-8 -*-
# Policy Gradients——帶基准線的REINFORCE算法(REINFORCE with Baseline)
# REINFORCE算法缺點:不同路徑之間的方差大,導致訓練不穩定
# 引入一控制變量sum(gamma^t * reward)的期望:E(sum(gamma^t * reward)),以減小方差
# Baseline:the mean of the discounted rewards
# The CartPole example
# https://www.cnblogs.com/kailugaji/
import gym
import ptan
import numpy as np
from tensorboardX import SummaryWriter
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
GAMMA = 0.99 # 折扣率
LEARNING_RATE = 0.01 # 學習率
EPISODES_TO_TRAIN = 4 # how many complete episodes we will use for training
# 構建網絡
class PGN(nn.Module):
def __init__(self, input_size, n_actions):
# input_size:輸入狀態維度,hidden_size:隱層維度=128,n_actions:輸出動作維度
super(PGN, self).__init__()
self.net = nn.Sequential(
nn.Linear(input_size, 128), # 全連接層,隱層預設為128維度
nn.ReLU(),
nn.Linear(128, n_actions) # 全連接層
)
def forward(self, x):
return self.net(x) # 未用softmax
# 與上一個程序唯一的不同在這!!!
# sum(gamma^t * reward) - E(sum(gamma^t * reward))
def calc_qvals(rewards):
res = []
sum_r = 0.0
for r in reversed(rewards):
sum_r *= GAMMA
sum_r += r
res.append(sum_r)
res = list(reversed(res))
mean_q = np.mean(res)
return [q - mean_q for q in res]
if __name__ == "__main__":
env = gym.make("CartPole-v0") # 創建游戲環境
writer = SummaryWriter(comment="-cartpole-reinforce-baseline")
net = PGN(env.observation_space.shape[0], env.action_space.n) # 4(狀態)->128->2(動作)
# print(net)
agent = ptan.agent.PolicyAgent(net, preprocessor=ptan.agent.float32_preprocessor,apply_softmax=True)
# PolicyAgent:連續
# make a decision about actions for every observation (依概率)
# apply_softmax=True:網絡輸出先經過softmax轉化成概率,再從這個概率分布中進行隨機抽樣
# float32_preprocessor:returns the observation as float64 instead of the float32 required by PyTorch
exp_source = ptan.experience.ExperienceSourceFirstLast(env, agent, gamma=GAMMA)
# 返回運行記錄以用於訓練模型,輸出格式為:(state, action, reward, last_state)
optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE) # Adam優化
total_rewards = [] # 前幾局的獎勵之和
step_idx = 0 # 迭代次數/輪數
done_episodes = 0 # 局數,幾局游戲
batch_episodes = 0
batch_states, batch_actions, batch_qvals = [], [], []
cur_states, cur_actions, cur_rewards = [], [], []
for step_idx, exp in enumerate(exp_source): # (state, action, reward, last_state)
cur_states.append(exp.state) # 狀態
cur_actions.append(int(exp.action)) # 動作
cur_rewards.append(exp.reward) # 即時獎勵
if exp.last_state is None: # 一局游戲結束
batch_states.extend(cur_states)
batch_actions.extend(cur_actions)
batch_qvals.extend(calc_qvals(cur_rewards))
cur_states.clear()
cur_actions.clear()
cur_rewards.clear()
batch_episodes += 1
# handle new rewards
new_rewards = exp_source.pop_total_rewards() # 返回一局游戲過后的total_rewords
if new_rewards:
done_episodes += 1 # 游戲局數(回合數)
reward = new_rewards[0]
total_rewards.append(reward) # the total rewards for the episodes
mean_rewards = float(np.mean(total_rewards[-100:])) # 平均獎勵
print("第%d次: 第%d局游戲結束, 獎勵為%6.2f, 平均獎勵為%6.2f" % (step_idx, done_episodes, reward, mean_rewards))
writer.add_scalar("reward", reward, step_idx)
writer.add_scalar("reward_100", mean_rewards, step_idx)
writer.add_scalar("episodes", done_episodes, step_idx)
if mean_rewards > 50: # 最大期望獎勵閾值,只有當mean_rewards > 50時才結束游戲
print("經過%d輪完成%d局游戲!" % (step_idx, done_episodes))
break
if batch_episodes < EPISODES_TO_TRAIN: # how many complete episodes we will use for training
continue
states_v = torch.FloatTensor(batch_states)
batch_actions_t = torch.LongTensor(batch_actions)
batch_qvals_v = torch.FloatTensor(batch_qvals)
# train
optimizer.zero_grad()
logits_v = net(states_v) # 輸入狀態,輸出Q(s, a)值
log_prob_v = F.log_softmax(logits_v, dim=1) # 輸出動作的對數概率分布 log π(s, a)
log_prob_actions_v = batch_qvals_v * log_prob_v[range(len(batch_states)), batch_actions_t]
# max (sum(gamma^t * reward) - E(sum(gamma^t * reward))) * log π(s, a)
loss_v = -log_prob_actions_v.mean() # min
loss_v.backward()
optimizer.step()
batch_episodes = 0
batch_states.clear()
batch_actions.clear()
batch_qvals.clear()
writer.close()
3.2 結果
第14次: 第1局游戲結束, 獎勵為 14.00, 平均獎勵為 14.00
第35次: 第2局游戲結束, 獎勵為 21.00, 平均獎勵為 17.50
第63次: 第3局游戲結束, 獎勵為 28.00, 平均獎勵為 21.00
第84次: 第4局游戲結束, 獎勵為 21.00, 平均獎勵為 21.00
第115次: 第5局游戲結束, 獎勵為 31.00, 平均獎勵為 23.00
第131次: 第6局游戲結束, 獎勵為 16.00, 平均獎勵為 21.83
第146次: 第7局游戲結束, 獎勵為 15.00, 平均獎勵為 20.86
第180次: 第8局游戲結束, 獎勵為 34.00, 平均獎勵為 22.50
第222次: 第9局游戲結束, 獎勵為 42.00, 平均獎勵為 24.67
第260次: 第10局游戲結束, 獎勵為 38.00, 平均獎勵為 26.00
第273次: 第11局游戲結束, 獎勵為 13.00, 平均獎勵為 24.82
第300次: 第12局游戲結束, 獎勵為 27.00, 平均獎勵為 25.00
第324次: 第13局游戲結束, 獎勵為 24.00, 平均獎勵為 24.92
第346次: 第14局游戲結束, 獎勵為 22.00, 平均獎勵為 24.71
第376次: 第15局游戲結束, 獎勵為 30.00, 平均獎勵為 25.07
第445次: 第16局游戲結束, 獎勵為 69.00, 平均獎勵為 27.81
第520次: 第17局游戲結束, 獎勵為 75.00, 平均獎勵為 30.59
第603次: 第18局游戲結束, 獎勵為 83.00, 平均獎勵為 33.50
第640次: 第19局游戲結束, 獎勵為 37.00, 平均獎勵為 33.68
第715次: 第20局游戲結束, 獎勵為 75.00, 平均獎勵為 35.75
第775次: 第21局游戲結束, 獎勵為 60.00, 平均獎勵為 36.90
第798次: 第22局游戲結束, 獎勵為 23.00, 平均獎勵為 36.27
第822次: 第23局游戲結束, 獎勵為 24.00, 平均獎勵為 35.74
第840次: 第24局游戲結束, 獎勵為 18.00, 平均獎勵為 35.00
第872次: 第25局游戲結束, 獎勵為 32.00, 平均獎勵為 34.88
第922次: 第26局游戲結束, 獎勵為 50.00, 平均獎勵為 35.46
第1016次: 第27局游戲結束, 獎勵為 94.00, 平均獎勵為 37.63
第1037次: 第28局游戲結束, 獎勵為 21.00, 平均獎勵為 37.04
第1083次: 第29局游戲結束, 獎勵為 46.00, 平均獎勵為 37.34
第1107次: 第30局游戲結束, 獎勵為 24.00, 平均獎勵為 36.90
第1153次: 第31局游戲結束, 獎勵為 46.00, 平均獎勵為 37.19
第1212次: 第32局游戲結束, 獎勵為 59.00, 平均獎勵為 37.88
第1245次: 第33局游戲結束, 獎勵為 33.00, 平均獎勵為 37.73
第1280次: 第34局游戲結束, 獎勵為 35.00, 平均獎勵為 37.65
第1359次: 第35局游戲結束, 獎勵為 79.00, 平均獎勵為 38.83
第1391次: 第36局游戲結束, 獎勵為 32.00, 平均獎勵為 38.64
第1524次: 第37局游戲結束, 獎勵為133.00, 平均獎勵為 41.19
第1581次: 第38局游戲結束, 獎勵為 57.00, 平均獎勵為 41.61
第1764次: 第39局游戲結束, 獎勵為183.00, 平均獎勵為 45.23
第1847次: 第40局游戲結束, 獎勵為 83.00, 平均獎勵為 46.17
第1898次: 第41局游戲結束, 獎勵為 51.00, 平均獎勵為 46.29
第1973次: 第42局游戲結束, 獎勵為 75.00, 平均獎勵為 46.98
第1996次: 第43局游戲結束, 獎勵為 23.00, 平均獎勵為 46.42
第2022次: 第44局游戲結束, 獎勵為 26.00, 平均獎勵為 45.95
第2092次: 第45局游戲結束, 獎勵為 70.00, 平均獎勵為 46.49
第2120次: 第46局游戲結束, 獎勵為 28.00, 平均獎勵為 46.09
第2154次: 第47局游戲結束, 獎勵為 34.00, 平均獎勵為 45.83
第2257次: 第48局游戲結束, 獎勵為103.00, 平均獎勵為 47.02
第2334次: 第49局游戲結束, 獎勵為 77.00, 平均獎勵為 47.63
第2439次: 第50局游戲結束, 獎勵為105.00, 平均獎勵為 48.78
第2508次: 第51局游戲結束, 獎勵為 69.00, 平均獎勵為 49.18
第2543次: 第52局游戲結束, 獎勵為 35.00, 平均獎勵為 48.90
第2630次: 第53局游戲結束, 獎勵為 87.00, 平均獎勵為 49.62
第2685次: 第54局游戲結束, 獎勵為 55.00, 平均獎勵為 49.72
第2705次: 第55局游戲結束, 獎勵為 20.00, 平均獎勵為 49.18
第2752次: 第56局游戲結束, 獎勵為 47.00, 平均獎勵為 49.14
第2862次: 第57局游戲結束, 獎勵為110.00, 平均獎勵為 50.21
經過2862輪完成57局游戲!
4. 04_cartpole_pg.py
4.1 程序
#!/usr/bin/env python3
# -*- coding=utf-8 -*-
# Policy gradient methods on CartPole
# 為增加探索,引入entropy bonus(信息熵正則項)
# 為了鼓勵模型加入更多的不確定性,這樣在訓練的時候,模型就會去探索更多的可能性
# H(π) = - sum(π(a|s) * log π(a|s))
# min -(the discounted reward - baseline) * log π(s, a) + beta * sum (π(s, a) * log π(s, a))
# https://www.cnblogs.com/kailugaji/
import gym
import ptan
import numpy as np
from tensorboardX import SummaryWriter
from typing import Optional
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
GAMMA = 0.99 # 折扣率
LEARNING_RATE = 0.01 # 學習率
ENTROPY_BETA = 0.01 # 熵正則化因子 the scale of the entropy bonus
BATCH_SIZE = 16 # 一批xx個樣本
REWARD_STEPS = 10
# 用於說明一條記錄中包含的步(step)數 (sub-trajectories of length 10)
# how many steps ahead the Bellman equation is unrolled to estimate the discounted total reward of every transition.
# 構建網絡
class PGN(nn.Module):
def __init__(self, input_size, n_actions):
# input_size:輸入狀態維度,hidden_size:隱層維度=128,n_actions:輸出動作維度
super(PGN, self).__init__()
self.net = nn.Sequential(
nn.Linear(input_size, 128), # 全連接層,隱層預設為128維度
nn.ReLU(),
nn.Linear(128, n_actions) # 全連接層
)
def forward(self, x):
return self.net(x) # 未用softmax
# 平滑
def smooth(old: Optional[float], val: float, alpha: float = 0.95) -> float:
if old is None:
return val
return old * alpha + (1-alpha)*val
if __name__ == "__main__":
env = gym.make("CartPole-v0") # 創建游戲環境
writer = SummaryWriter(comment="-cartpole-pg")
net = PGN(env.observation_space.shape[0], env.action_space.n) # 4(狀態)->128->2(動作)
# print(net)
agent = ptan.agent.PolicyAgent(net, preprocessor=ptan.agent.float32_preprocessor, apply_softmax=True)
# PolicyAgent:連續
# make a decision about actions for every observation (依概率)
# apply_softmax=True:網絡輸出先經過softmax轉化成概率,再從這個概率分布中進行隨機抽樣
# float32_preprocessor:returns the observation as float64 instead of the float32 required by PyTorch
exp_source = ptan.experience.ExperienceSourceFirstLast(env, agent, gamma=GAMMA, steps_count=REWARD_STEPS)
# 返回運行記錄以用於訓練模型,輸出格式為:(state, action, reward, last_state)
# 並不會輸出每一步的信息,而是把多步的交互結果綜合(累計多步的reward;顯示頭尾的狀態)到一條Experience輸出
# 多步rewards的累加是有衰退的,而其中的衰退系數由參數gamma(折扣率)指定,即reward=r1+gamma∗r2+(gamma^2)∗r3
# 其中rn代表第n步操作獲得的reward
# last_state: the state we've got after executing the action. If our episode ends, we have None here
# steps_count=REWARD_STEPS:unroll the Bellman equation for 10 steps
optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE) # Adam優化
total_rewards = [] # 前幾局的獎勵之和
step_rewards = []
step_idx = 0 # 迭代次數/輪數
done_episodes = 0 # 局數,幾局游戲
reward_sum = 0.0 # the sum of the discounted reward for every transition
bs_smoothed = entropy = l_entropy = l_policy = l_total = None
batch_states, batch_actions, batch_scales = [], [], []
for step_idx, exp in enumerate(exp_source): # (state, action, reward, last_state)
reward_sum += exp.reward # the sum of the discounted reward for every transition
baseline = reward_sum / (step_idx + 1) # 獎勵除以迭代次數(步數) the baseline for the policy scale
writer.add_scalar("baseline", baseline, step_idx)
batch_states.append(exp.state) # 狀態
batch_actions.append(int(exp.action)) # 動作
batch_scales.append(exp.reward - baseline) # 優勢函數,引入基准
# handle new rewards
new_rewards = exp_source.pop_total_rewards() # 返回一局游戲過后的total_rewords
if new_rewards:
done_episodes += 1 # 游戲局數(回合數)
reward = new_rewards[0] # 本局游戲獎勵
total_rewards.append(reward) # 前幾局的獎勵之和
mean_rewards = float(np.mean(total_rewards[-100:])) # 前幾局的獎勵之和/回合數
print("第%d次: 第%d局游戲結束, 獎勵為%6.2f, 平均獎勵為%6.2f" % (step_idx, done_episodes, reward, mean_rewards))
writer.add_scalar("reward", reward, step_idx) # 本局游戲獎勵
writer.add_scalar("reward_100", mean_rewards, step_idx) # 前幾局游戲的平均獎勵
writer.add_scalar("episodes", done_episodes, step_idx) # 游戲局數(回合數)
if mean_rewards > 50: # 最大期望獎勵閾值,只有當mean_rewards > 50時才結束游戲
print("經過%d輪完成%d局游戲!" % (step_idx, done_episodes))
break
if len(batch_states) < BATCH_SIZE: # state里面還沒超過BATCH_SIZE個樣本
continue
states_v = torch.FloatTensor(batch_states)
batch_actions_t = torch.LongTensor(batch_actions)
batch_scale_v = torch.FloatTensor(batch_scales) # 優勢函數,引入基准
# train
optimizer.zero_grad()
logits_v = net(states_v) # 輸入狀態,輸出Q(s, a)值
log_prob_v = F.log_softmax(logits_v, dim=1) # 輸出動作的對數概率分布 log π(s, a)
log_prob_actions_v = batch_scale_v * log_prob_v[range(BATCH_SIZE), batch_actions_t]
# max (the discounted reward - baseline) * log π(s, a)
loss_policy_v = -log_prob_actions_v.mean() # min
# add the entropy bonus to the loss
prob_v = F.softmax(logits_v, dim=1) # 輸出動作的概率分布π(s, a)
entropy_v = -(prob_v * log_prob_v).sum(dim=1).mean() # 熵正則項
# 信息熵的計算公式:entropy = -sum (π(s, a) * log π(s, a))
entropy_loss_v = -ENTROPY_BETA * entropy_v # loss = - beta * entropy
loss_v = loss_policy_v + entropy_loss_v
# min -(the discounted reward - baseline) * log π(s, a) + beta * sum (π(s, a) * log π(s, a))
loss_v.backward()
optimizer.step()
# calculate the Kullback-Leibler (KL) divergence between the new policy and the old policy
new_logits_v = net(states_v) # 輸入狀態,輸出Q(s, a)值
new_prob_v = F.softmax(new_logits_v, dim=1) # 輸出動作的概率分布π(s, a)
kl_div_v = -((new_prob_v / prob_v).log() * prob_v).sum(dim=1).mean()
# KL散度的計算公式:KL = - sum(log(π'(s, a)/π(s, a)) * π(s, a))
writer.add_scalar("kl", kl_div_v.item(), step_idx)
# calculate the statistics about the gradients on this training step
grad_max = 0.0
grad_means = 0.0
grad_count = 0
for p in net.parameters():
grad_max = max(grad_max, p.grad.abs().max().item()) # the graph of the maximum
grad_means += (p.grad ** 2).mean().sqrt().item() # L2 norm of gradients
grad_count += 1
# 下面實際上沒有平滑,返回實際值(這5行代碼在本程序中沒意義)
bs_smoothed = smooth(bs_smoothed, np.mean(batch_scales))
entropy = smooth(entropy, entropy_v.item())
l_entropy = smooth(l_entropy, entropy_loss_v.item())
l_policy = smooth(l_policy, loss_policy_v.item())
l_total = smooth(l_total, loss_v.item())
writer.add_scalar("baseline", baseline, step_idx)
writer.add_scalar("entropy", entropy, step_idx)
writer.add_scalar("loss_entropy", l_entropy, step_idx)
writer.add_scalar("loss_policy", l_policy, step_idx)
writer.add_scalar("loss_total", l_total, step_idx)
writer.add_scalar("grad_l2", grad_means / grad_count, step_idx)
writer.add_scalar("grad_max", grad_max, step_idx)
writer.add_scalar("batch_scales", bs_smoothed, step_idx)
batch_states.clear()
batch_actions.clear()
batch_scales.clear()
writer.close()
4.2 結果
第16次: 第1局游戲結束, 獎勵為 16.00, 平均獎勵為 16.00
第35次: 第2局游戲結束, 獎勵為 19.00, 平均獎勵為 17.50
第72次: 第3局游戲結束, 獎勵為 37.00, 平均獎勵為 24.00
第90次: 第4局游戲結束, 獎勵為 18.00, 平均獎勵為 22.50
第100次: 第5局游戲結束, 獎勵為 10.00, 平均獎勵為 20.00
第121次: 第6局游戲結束, 獎勵為 21.00, 平均獎勵為 20.17
第130次: 第7局游戲結束, 獎勵為 9.00, 平均獎勵為 18.57
第143次: 第8局游戲結束, 獎勵為 13.00, 平均獎勵為 17.88
第156次: 第9局游戲結束, 獎勵為 13.00, 平均獎勵為 17.33
第170次: 第10局游戲結束, 獎勵為 14.00, 平均獎勵為 17.00
第185次: 第11局游戲結束, 獎勵為 15.00, 平均獎勵為 16.82
第198次: 第12局游戲結束, 獎勵為 13.00, 平均獎勵為 16.50
第224次: 第13局游戲結束, 獎勵為 26.00, 平均獎勵為 17.23
第253次: 第14局游戲結束, 獎勵為 29.00, 平均獎勵為 18.07
第323次: 第15局游戲結束, 獎勵為 70.00, 平均獎勵為 21.53
第356次: 第16局游戲結束, 獎勵為 33.00, 平均獎勵為 22.25
第388次: 第17局游戲結束, 獎勵為 32.00, 平均獎勵為 22.82
第414次: 第18局游戲結束, 獎勵為 26.00, 平均獎勵為 23.00
第442次: 第19局游戲結束, 獎勵為 28.00, 平均獎勵為 23.26
第536次: 第20局游戲結束, 獎勵為 94.00, 平均獎勵為 26.80
第589次: 第21局游戲結束, 獎勵為 53.00, 平均獎勵為 28.05
第652次: 第22局游戲結束, 獎勵為 63.00, 平均獎勵為 29.64
第753次: 第23局游戲結束, 獎勵為101.00, 平均獎勵為 32.74
第860次: 第24局游戲結束, 獎勵為107.00, 平均獎勵為 35.83
第904次: 第25局游戲結束, 獎勵為 44.00, 平均獎勵為 36.16
第984次: 第26局游戲結束, 獎勵為 80.00, 平均獎勵為 37.85
第1174次: 第27局游戲結束, 獎勵為190.00, 平均獎勵為 43.48
第1236次: 第28局游戲結束, 獎勵為 62.00, 平均獎勵為 44.14
第1317次: 第29局游戲結束, 獎勵為 81.00, 平均獎勵為 45.41
第1381次: 第30局游戲結束, 獎勵為 64.00, 平均獎勵為 46.03
第1581次: 第31局游戲結束, 獎勵為200.00, 平均獎勵為 51.00
經過1581輪完成31局游戲!
The baseline value during the training
Batch scales
Entropy during the training
Entropy loss
Policy loss
Total loss
從Loss結果看,這次實驗並不理想,可以多運行幾次,得到更好的結果。
5. 前四個算法的總體結果對比
藍線:DQN(01_cartpole_dqn.py)
黑線:REINFORCE(02_cartpole_reinforce.py)
紅線:REINFORCE with Baseline(03_cartpole_reinforce_baseline.py)
黃線:策略梯度法(04_cartpole_pg.py)
Reward
Average reward
Episodes
6. 06_cartpole_pg.py
6.1 程序
#!/usr/bin/env python3 # -*- coding=utf-8 -*- # Policy gradient methods on CartPole # 為增加探索,引入entropy bonus(信息熵正則項) # 為了鼓勵模型加入更多的不確定性,這樣在訓練的時候,模型就會去探索更多的可能性 # H(π) = - sum(π(a|s) * log π(a|s)) # 與03 Policy Gradients/04_cartpole_pg.py基本一致,唯一不同是Baseline可選擇,加或者不加 # 加:min -(the discounted reward - baseline) * log π(s, a) + beta * sum (π(s, a) * log π(s, a)) # 不加:min -(the discounted reward) * log π(s, a) + beta * sum (π(s, a) * log π(s, a)) # https://www.cnblogs.com/kailugaji/ import gym import ptan import argparse import numpy as np from tensorboardX import SummaryWriter import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim GAMMA = 0.99 # 折扣率 LEARNING_RATE = 0.01 # 學習率 ENTROPY_BETA = 0.01 # 熵正則化因子 the scale of the entropy bonus BATCH_SIZE = 16 # 一批xx個樣本 REWARD_STEPS = 10 # 用於說明一條記錄中包含的步(step)數 (sub-trajectories of length 10) # how many steps ahead the Bellman equation is unrolled to estimate the discounted total reward of every transition. # 構建網絡 class PGN(nn.Module): def __init__(self, input_size, n_actions): # input_size:輸入狀態維度,hidden_size:隱層維度=128,n_actions:輸出動作維度 super(PGN, self).__init__() self.net = nn.Sequential( nn.Linear(input_size, 128), # 全連接層,隱層預設為128維度 nn.ReLU(), nn.Linear(128, n_actions) # 全連接層 ) def forward(self, x): return self.net(x) # 未用softmax if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--baseline", default=False, action='store_true', help="Enable mean baseline") args = parser.parse_args() args.baseline = "True" # 加baseline env = gym.make("CartPole-v0") # 創建游戲環境 writer = SummaryWriter(comment="-cartpole-pg" + "-baseline=%s" % args.baseline) net = PGN(env.observation_space.shape[0], env.action_space.n) # 4(狀態)->128->2(動作) # print(net) agent = ptan.agent.PolicyAgent(net, preprocessor=ptan.agent.float32_preprocessor, apply_softmax=True) # PolicyAgent:連續 # make a decision about actions for every observation (依概率) # apply_softmax=True:網絡輸出先經過softmax轉化成概率,再從這個概率分布中進行隨機抽樣 # float32_preprocessor:returns the observation as float64 instead of the float32 required by PyTorch exp_source = ptan.experience.ExperienceSourceFirstLast(env, agent, gamma=GAMMA, steps_count=REWARD_STEPS) # 返回運行記錄以用於訓練模型,輸出格式為:(state, action, reward, last_state) # 並不會輸出每一步的信息,而是把多步的交互結果綜合(累計多步的reward;顯示頭尾的狀態)到一條Experience輸出 # 多步rewards的累加是有衰退的,而其中的衰退系數由參數gamma(折扣率)指定,即reward=r1+gamma∗r2+(gamma^2)∗r3 # 其中rn代表第n步操作獲得的reward # last_state: the state we've got after executing the action. If our episode ends, we have None here # steps_count=REWARD_STEPS:unroll the Bellman equation for 10 steps optimizer = optim.Adam(net.parameters(), lr=LEARNING_RATE) # Adam優化 total_rewards = [] # 前幾局的獎勵之和 step_rewards = [] step_idx = 0 # 迭代次數/輪數 done_episodes = 0 # 局數,幾局游戲 reward_sum = 0.0 # the sum of the discounted reward for every transition batch_states, batch_actions, batch_scales = [], [], [] for step_idx, exp in enumerate(exp_source): # (state, action, reward, last_state) reward_sum += exp.reward # the sum of the discounted reward for every transition baseline = reward_sum / (step_idx + 1) # 獎勵除以迭代次數(步數) the baseline for the policy scale writer.add_scalar("baseline", baseline, step_idx) batch_states.append(exp.state) # 狀態 batch_actions.append(int(exp.action)) # 動作 if args.baseline: # True batch_scales.append(exp.reward - baseline) # 優勢函數,引入基准 else: # False batch_scales.append(exp.reward) # 沒有基准 # handle new rewards new_rewards = exp_source.pop_total_rewards() # 返回一局游戲過后的total_rewords if new_rewards: done_episodes += 1 # 游戲局數(回合數) reward = new_rewards[0] # 本局游戲獎勵 total_rewards.append(reward) # 前幾局的獎勵之和 mean_rewards = float(np.mean(total_rewards[-100:])) # 平均獎勵:前幾局的獎勵之和/回合數 print("第%d次: 第%d局游戲結束, 獎勵為%6.2f, 平均獎勵為%6.2f" % (step_idx, done_episodes, reward, mean_rewards)) writer.add_scalar("reward", reward, step_idx) # 本局游戲獎勵 writer.add_scalar("reward_100", mean_rewards, step_idx) # 前幾局游戲的平均獎勵 writer.add_scalar("episodes", done_episodes, step_idx) # 游戲局數(回合數) if mean_rewards > 50: # 最大期望獎勵閾值,只有當mean_rewards > 50時才結束游戲 print("經過%d輪完成%d局游戲!" % (step_idx, done_episodes)) break if len(batch_states) < BATCH_SIZE: # state里面還沒超過BATCH_SIZE個樣本 continue states_v = torch.FloatTensor(batch_states) batch_actions_t = torch.LongTensor(batch_actions) batch_scale_v = torch.FloatTensor(batch_scales) # r 或者 優勢函數(r - b) # train optimizer.zero_grad() logits_v = net(states_v) # 輸入狀態,輸出Q(s, a)值 log_prob_v = F.log_softmax(logits_v, dim=1) # 輸出動作的對數概率分布 log π(s, a) log_prob_actions_v = batch_scale_v * log_prob_v[range(BATCH_SIZE), batch_actions_t] # 加基准:max (the discounted reward - baseline) * log π(s, a) # 不加基准:max (the discounted reward) * log π(s, a) loss_policy_v = -log_prob_actions_v.mean() # min loss_policy_v.backward(retain_graph=True) grads = np.concatenate([p.grad.data.numpy().flatten() for p in net.parameters() if p.grad is not None]) # add the entropy bonus to the loss prob_v = F.softmax(logits_v, dim=1) # 輸出動作的概率分布π(s, a) entropy_v = -(prob_v * log_prob_v).sum(dim=1).mean() # 熵正則項 # 信息熵的計算公式:entropy = -sum (π(s, a) * log π(s, a)) entropy_loss_v = -ENTROPY_BETA * entropy_v # loss = - beta * entropy entropy_loss_v.backward() optimizer.step() loss_v = loss_policy_v + entropy_loss_v # 加基准:min -(the discounted reward - baseline) * log π(s, a) + beta * sum (π(s, a) * log π(s, a)) # 不加:min -(the discounted reward) * log π(s, a) + beta * sum (π(s, a) * log π(s, a)) # calculate the Kullback-Leibler (KL) divergence between the new policy and the old policy new_logits_v = net(states_v) # 輸入狀態,輸出Q(s, a)值 new_prob_v = F.softmax(new_logits_v, dim=1) # 輸出動作的概率分布π(s, a) kl_div_v = -((new_prob_v / prob_v).log() * prob_v).sum(dim=1).mean() # KL散度的計算公式:KL = - sum(log(π'(s, a)/π(s, a)) * π(s, a)) writer.add_scalar("kl", kl_div_v.item(), step_idx) writer.add_scalar("baseline", baseline, step_idx) writer.add_scalar("entropy", entropy_v.item(), step_idx) writer.add_scalar("batch_scales", np.mean(batch_scales), step_idx) writer.add_scalar("loss_entropy", entropy_loss_v.item(), step_idx) writer.add_scalar("loss_policy", loss_policy_v.item(), step_idx) writer.add_scalar("loss_total", loss_v.item(), step_idx) # calculate the statistics about the gradients on this training step g_l2 = np.sqrt(np.mean(np.square(grads))) # L2 norm of gradients g_max = np.max(np.abs(grads)) # the graph of the maximum writer.add_scalar("grad_l2", g_l2, step_idx) writer.add_scalar("grad_max", g_max, step_idx) writer.add_scalar("grad_var", np.var(grads), step_idx) # 梯度方差 batch_states.clear() batch_actions.clear() batch_scales.clear() writer.close()
6.2 結果
當不加baseline時:
第32次: 第1局游戲結束, 獎勵為 32.00, 平均獎勵為 32.00 第47次: 第2局游戲結束, 獎勵為 15.00, 平均獎勵為 23.50 第65次: 第3局游戲結束, 獎勵為 18.00, 平均獎勵為 21.67 第74次: 第4局游戲結束, 獎勵為 9.00, 平均獎勵為 18.50 第87次: 第5局游戲結束, 獎勵為 13.00, 平均獎勵為 17.40 第101次: 第6局游戲結束, 獎勵為 14.00, 平均獎勵為 16.83 第113次: 第7局游戲結束, 獎勵為 12.00, 平均獎勵為 16.14 第124次: 第8局游戲結束, 獎勵為 11.00, 平均獎勵為 15.50 第138次: 第9局游戲結束, 獎勵為 14.00, 平均獎勵為 15.33 第148次: 第10局游戲結束, 獎勵為 10.00, 平均獎勵為 14.80 第159次: 第11局游戲結束, 獎勵為 11.00, 平均獎勵為 14.45 第170次: 第12局游戲結束, 獎勵為 11.00, 平均獎勵為 14.17 第181次: 第13局游戲結束, 獎勵為 11.00, 平均獎勵為 13.92 第200次: 第14局游戲結束, 獎勵為 19.00, 平均獎勵為 14.29 第210次: 第15局游戲結束, 獎勵為 10.00, 平均獎勵為 14.00 第225次: 第16局游戲結束, 獎勵為 15.00, 平均獎勵為 14.06 第238次: 第17局游戲結束, 獎勵為 13.00, 平均獎勵為 14.00 第250次: 第18局游戲結束, 獎勵為 12.00, 平均獎勵為 13.89 第262次: 第19局游戲結束, 獎勵為 12.00, 平均獎勵為 13.79 第275次: 第20局游戲結束, 獎勵為 13.00, 平均獎勵為 13.75 第288次: 第21局游戲結束, 獎勵為 13.00, 平均獎勵為 13.71 第302次: 第22局游戲結束, 獎勵為 14.00, 平均獎勵為 13.73 第323次: 第23局游戲結束, 獎勵為 21.00, 平均獎勵為 14.04 第339次: 第24局游戲結束, 獎勵為 16.00, 平均獎勵為 14.12 第358次: 第25局游戲結束, 獎勵為 19.00, 平均獎勵為 14.32 第369次: 第26局游戲結束, 獎勵為 11.00, 平均獎勵為 14.19 第384次: 第27局游戲結束, 獎勵為 15.00, 平均獎勵為 14.22 第404次: 第28局游戲結束, 獎勵為 20.00, 平均獎勵為 14.43 第428次: 第29局游戲結束, 獎勵為 24.00, 平均獎勵為 14.76 第444次: 第30局游戲結束, 獎勵為 16.00, 平均獎勵為 14.80 第457次: 第31局游戲結束, 獎勵為 13.00, 平均獎勵為 14.74 第475次: 第32局游戲結束, 獎勵為 18.00, 平均獎勵為 14.84 第497次: 第33局游戲結束, 獎勵為 22.00, 平均獎勵為 15.06 第511次: 第34局游戲結束, 獎勵為 14.00, 平均獎勵為 15.03 第534次: 第35局游戲結束, 獎勵為 23.00, 平均獎勵為 15.26 第579次: 第36局游戲結束, 獎勵為 45.00, 平均獎勵為 16.08 第600次: 第37局游戲結束, 獎勵為 21.00, 平均獎勵為 16.22 第623次: 第38局游戲結束, 獎勵為 23.00, 平均獎勵為 16.39 第650次: 第39局游戲結束, 獎勵為 27.00, 平均獎勵為 16.67 第667次: 第40局游戲結束, 獎勵為 17.00, 平均獎勵為 16.68 第718次: 第41局游戲結束, 獎勵為 51.00, 平均獎勵為 17.51 第746次: 第42局游戲結束, 獎勵為 28.00, 平均獎勵為 17.76 第792次: 第43局游戲結束, 獎勵為 46.00, 平均獎勵為 18.42 第834次: 第44局游戲結束, 獎勵為 42.00, 平均獎勵為 18.95 第882次: 第45局游戲結束, 獎勵為 48.00, 平均獎勵為 19.60 第923次: 第46局游戲結束, 獎勵為 41.00, 平均獎勵為 20.07 第953次: 第47局游戲結束, 獎勵為 30.00, 平均獎勵為 20.28 第983次: 第48局游戲結束, 獎勵為 30.00, 平均獎勵為 20.48 第1071次: 第49局游戲結束, 獎勵為 88.00, 平均獎勵為 21.86 第1160次: 第50局游戲結束, 獎勵為 89.00, 平均獎勵為 23.20 第1287次: 第51局游戲結束, 獎勵為127.00, 平均獎勵為 25.24 第1367次: 第52局游戲結束, 獎勵為 80.00, 平均獎勵為 26.29 第1469次: 第53局游戲結束, 獎勵為102.00, 平均獎勵為 27.72 第1533次: 第54局游戲結束, 獎勵為 64.00, 平均獎勵為 28.39 第1589次: 第55局游戲結束, 獎勵為 56.00, 平均獎勵為 28.89 第1618次: 第56局游戲結束, 獎勵為 29.00, 平均獎勵為 28.89 第1651次: 第57局游戲結束, 獎勵為 33.00, 平均獎勵為 28.96 第1697次: 第58局游戲結束, 獎勵為 46.00, 平均獎勵為 29.26 第1707次: 第59局游戲結束, 獎勵為 10.00, 平均獎勵為 28.93 第1747次: 第60局游戲結束, 獎勵為 40.00, 平均獎勵為 29.12 第1778次: 第61局游戲結束, 獎勵為 31.00, 平均獎勵為 29.15 第1802次: 第62局游戲結束, 獎勵為 24.00, 平均獎勵為 29.06 第1820次: 第63局游戲結束, 獎勵為 18.00, 平均獎勵為 28.89 第1850次: 第64局游戲結束, 獎勵為 30.00, 平均獎勵為 28.91 第1862次: 第65局游戲結束, 獎勵為 12.00, 平均獎勵為 28.65 第1883次: 第66局游戲結束, 獎勵為 21.00, 平均獎勵為 28.53 第1919次: 第67局游戲結束, 獎勵為 36.00, 平均獎勵為 28.64 第1971次: 第68局游戲結束, 獎勵為 52.00, 平均獎勵為 28.99 第1996次: 第69局游戲結束, 獎勵為 25.00, 平均獎勵為 28.93 第2029次: 第70局游戲結束, 獎勵為 33.00, 平均獎勵為 28.99 第2104次: 第71局游戲結束, 獎勵為 75.00, 平均獎勵為 29.63 第2177次: 第72局游戲結束, 獎勵為 73.00, 平均獎勵為 30.24 第2270次: 第73局游戲結束, 獎勵為 93.00, 平均獎勵為 31.10 第2363次: 第74局游戲結束, 獎勵為 93.00, 平均獎勵為 31.93 第2530次: 第75局游戲結束, 獎勵為167.00, 平均獎勵為 33.73 第2608次: 第76局游戲結束, 獎勵為 78.00, 平均獎勵為 34.32 第2703次: 第77局游戲結束, 獎勵為 95.00, 平均獎勵為 35.10 第2854次: 第78局游戲結束, 獎勵為151.00, 平均獎勵為 36.59 第3054次: 第79局游戲結束, 獎勵為200.00, 平均獎勵為 38.66 第3152次: 第80局游戲結束, 獎勵為 98.00, 平均獎勵為 39.40 第3205次: 第81局游戲結束, 獎勵為 53.00, 平均獎勵為 39.57 第3228次: 第82局游戲結束, 獎勵為 23.00, 平均獎勵為 39.37 第3258次: 第83局游戲結束, 獎勵為 30.00, 平均獎勵為 39.25 第3279次: 第84局游戲結束, 獎勵為 21.00, 平均獎勵為 39.04 第3301次: 第85局游戲結束, 獎勵為 22.00, 平均獎勵為 38.84 第3328次: 第86局游戲結束, 獎勵為 27.00, 平均獎勵為 38.70 第3346次: 第87局游戲結束, 獎勵為 18.00, 平均獎勵為 38.46 第3366次: 第88局游戲結束, 獎勵為 20.00, 平均獎勵為 38.25 第3384次: 第89局游戲結束, 獎勵為 18.00, 平均獎勵為 38.02 第3399次: 第90局游戲結束, 獎勵為 15.00, 平均獎勵為 37.77 第3420次: 第91局游戲結束, 獎勵為 21.00, 平均獎勵為 37.58 第3440次: 第92局游戲結束, 獎勵為 20.00, 平均獎勵為 37.39 第3466次: 第93局游戲結束, 獎勵為 26.00, 平均獎勵為 37.27 第3489次: 第94局游戲結束, 獎勵為 23.00, 平均獎勵為 37.12 第3506次: 第95局游戲結束, 獎勵為 17.00, 平均獎勵為 36.91 第3531次: 第96局游戲結束, 獎勵為 25.00, 平均獎勵為 36.78 第3563次: 第97局游戲結束, 獎勵為 32.00, 平均獎勵為 36.73 第3592次: 第98局游戲結束, 獎勵為 29.00, 平均獎勵為 36.65 第3617次: 第99局游戲結束, 獎勵為 25.00, 平均獎勵為 36.54 第3678次: 第100局游戲結束, 獎勵為 61.00, 平均獎勵為 36.78 第3734次: 第101局游戲結束, 獎勵為 56.00, 平均獎勵為 37.02 第3814次: 第102局游戲結束, 獎勵為 80.00, 平均獎勵為 37.67 第3987次: 第103局游戲結束, 獎勵為173.00, 平均獎勵為 39.22 第4106次: 第104局游戲結束, 獎勵為119.00, 平均獎勵為 40.32 第4153次: 第105局游戲結束, 獎勵為 47.00, 平均獎勵為 40.66 第4229次: 第106局游戲結束, 獎勵為 76.00, 平均獎勵為 41.28 第4365次: 第107局游戲結束, 獎勵為136.00, 平均獎勵為 42.52 第4470次: 第108局游戲結束, 獎勵為105.00, 平均獎勵為 43.46 第4532次: 第109局游戲結束, 獎勵為 62.00, 平均獎勵為 43.94 第4588次: 第110局游戲結束, 獎勵為 56.00, 平均獎勵為 44.40 第4669次: 第111局游戲結束, 獎勵為 81.00, 平均獎勵為 45.10 第4736次: 第112局游戲結束, 獎勵為 67.00, 平均獎勵為 45.66 第4797次: 第113局游戲結束, 獎勵為 61.00, 平均獎勵為 46.16 第4890次: 第114局游戲結束, 獎勵為 93.00, 平均獎勵為 46.90 第4980次: 第115局游戲結束, 獎勵為 90.00, 平均獎勵為 47.70 第5050次: 第116局游戲結束, 獎勵為 70.00, 平均獎勵為 48.25 第5089次: 第117局游戲結束, 獎勵為 39.00, 平均獎勵為 48.51 第5140次: 第118局游戲結束, 獎勵為 51.00, 平均獎勵為 48.90 第5176次: 第119局游戲結束, 獎勵為 36.00, 平均獎勵為 49.14 第5207次: 第120局游戲結束, 獎勵為 31.00, 平均獎勵為 49.32 第5240次: 第121局游戲結束, 獎勵為 33.00, 平均獎勵為 49.52 第5278次: 第122局游戲結束, 獎勵為 38.00, 平均獎勵為 49.76 第5307次: 第123局游戲結束, 獎勵為 29.00, 平均獎勵為 49.84 第5351次: 第124局游戲結束, 獎勵為 44.00, 平均獎勵為 50.12 經過5351輪完成124局游戲!
當添加baseline時:
第18次: 第1局游戲結束, 獎勵為 18.00, 平均獎勵為 18.00 第36次: 第2局游戲結束, 獎勵為 18.00, 平均獎勵為 18.00 第58次: 第3局游戲結束, 獎勵為 22.00, 平均獎勵為 19.33 第80次: 第4局游戲結束, 獎勵為 22.00, 平均獎勵為 20.00 第92次: 第5局游戲結束, 獎勵為 12.00, 平均獎勵為 18.40 第116次: 第6局游戲結束, 獎勵為 24.00, 平均獎勵為 19.33 第187次: 第7局游戲結束, 獎勵為 71.00, 平均獎勵為 26.71 第228次: 第8局游戲結束, 獎勵為 41.00, 平均獎勵為 28.50 第253次: 第9局游戲結束, 獎勵為 25.00, 平均獎勵為 28.11 第276次: 第10局游戲結束, 獎勵為 23.00, 平均獎勵為 27.60 第352次: 第11局游戲結束, 獎勵為 76.00, 平均獎勵為 32.00 第459次: 第12局游戲結束, 獎勵為107.00, 平均獎勵為 38.25 第514次: 第13局游戲結束, 獎勵為 55.00, 平均獎勵為 39.54 第557次: 第14局游戲結束, 獎勵為 43.00, 平均獎勵為 39.79 第659次: 第15局游戲結束, 獎勵為102.00, 平均獎勵為 43.93 第859次: 第16局游戲結束, 獎勵為200.00, 平均獎勵為 53.69 經過859輪完成16局游戲!
The rewards of training episodes without the baseline (black) and with the baseline (blue)
The average rewards of training episodes without the baseline (black) and with the baseline (blue)
Total loss without the baseline (black) and with the baseline (blue)
Episodes without the baseline (black) and with the baseline (blue)
打開tensorboard:
activate RL cd .. D: cd D:\xxx\Deep-Reinforcement-Learning-Hands-On-Second-Edition-master\Chapter11 tensorboard --logdir=./runs http://localhost:6006/
7. 參考文獻
[1] https://github.com/PacktPublishing/Deep-Reinforcement-Learning-Hands-On-Second-Edition
[2] 強化學習(Reinforcement Learning) - 凱魯嘎吉 - 博客園
[3] https://github.com/kailugaji/Hands-on-Reinforcement-Learning/tree/main/03%20Policy%20Gradients