pytorch 笔记: DQN(experience replay)
生活随笔
收集整理的這篇文章主要介紹了
pytorch 笔记: DQN(experience replay)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1 理論知識
DQN 筆記 State-action Value Function(Q-function)_UQI-LIUWJ的博客-CSDN博客
強化學(xué)習(xí)筆記 experience replay 經(jīng)驗回放_UQI-LIUWJ的博客-CSDN博客
2 導(dǎo)入庫
import torch import torch.nn as nn import torch.nn.functional as F import numpy as np import gym3 定義參數(shù)
BATCH_SIZE = 32 # 從experience buffer 每一次提取,用于訓(xùn)練的batch大小LR = 0.01 # 學(xué)習(xí)率EPSILON = 0.9 # 貪婪策略指數(shù),Q-learning的一個指數(shù),用于指示是探索還是利用。GAMMA = 0.9 # 折扣回報TARGET_REPLACE_ITER = 100 # target network的更新頻率 #在100輪以內(nèi)固定target network,每100輪更新一次MEMORY_CAPACITY = 2000 #replay buffer 大小env = gym.make('CartPole-v0')N_ACTIONS = env.action_space.n #2 #每一個state時可以有幾個動作N_STATES = env.observation_space.shape[0] #4 #每一個state是幾維的向量4 用于計算action 權(quán)重的神經(jīng)網(wǎng)絡(luò)
????????Net的作用是輸入某一時刻的state向量,輸出是各個action的值
????????這里相比于policy network,這里輸出的時候不用softmax,因為這里是需要Q最大的action就可以了
class Net(nn.Module):def __init__(self, ):super(Net, self).__init__()self.fc1 = nn.Linear(N_STATES, 50)self.out = nn.Linear(50, N_ACTIONS)def forward(self, x):x = self.fc1(x)x = F.relu(x)actions_value = self.out(x)return actions_value5 創(chuàng)建Q-learning 模型
5.1 __init__
# 創(chuàng)建Q-learning的模型 class DQN(object):def __init__(self):# 兩張網(wǎng)結(jié)構(gòu)上是一樣的,不過就是target_net是每100次更新一次,eval_net每次都更新self.eval_net, self.target_net = Net(), Net()#eval_net:實時更新的Q的network#target_net:每TARGET_REPLACE_ITER輪更新一次的target networkself.learn_step_counter = 0 # 如果次數(shù)到了,更新target_net,那么target_net更新的輪數(shù)重置self.memory_counter = 0 # relay buffer 計數(shù)器self.memory = np.zeros((MEMORY_CAPACITY, N_STATES * 2 + 2)) # relay bufferself.optimizer = torch.optim.Adam(self.eval_net.parameters(), lr=LR)self.loss_func = nn.MSELoss()5.2 選擇動作
# 選擇動作def choose_action(self, x):x = torch.unsqueeze(torch.FloatTensor(x), 0)#print(state.shape) #torch.size([1,4])#當前狀態(tài)s對應(yīng)的向量,通過unsqueeze操作變成[1,4]維的向量#之前設(shè)置了EPSILON,用于控制是使用還是探索if np.random.uniform() < EPSILON: # 貪婪策略actions_value = self.eval_net(x)#eval_net是一個Net 類#actions_value 是每個action的Q值 (即Q(s,a)))action = torch.max(actions_value, 1)[1].data.numpy()#表示Q值最大的那個action的indexaction = action[0]# return the argmax index,在本例中,就是0或者1else: # randomaction = np.random.randint(0, N_ACTIONS)#此時使用的是探索return action5.3 存儲記憶
將transition的結(jié)果存入experience buffer中
def store_transition(self, s, a, r, s_):#s和s_是兩個ndarray(當前狀態(tài),使用了某個action之后的狀態(tài))# a和r是兩個數(shù),action和rewardtransition = np.hstack((s, [a, r], s_)) # 將參數(shù)打包起來,成為一個長一元ndarrayindex = self.memory_counter % MEMORY_CAPACITY#當前的transition需要存入/覆蓋的位置self.memory[index, :] = transitionself.memory_counter += 1 #更新memory5.4 模型學(xué)習(xí)
def learn(self):# target parameter updateif self.learn_step_counter % TARGET_REPLACE_ITER == 0:self.target_net.load_state_dict(self.eval_net.state_dict())#如果到了該更新target network的時候了,那么把eval_net此時的參數(shù)賦給target_net self.learn_step_counter += 1 # target network的計數(shù)sample_index = np.random.choice(MEMORY_CAPACITY, BATCH_SIZE)#從relay buffer中選擇一個batch的樣本index(可以重復(fù))b_memory = self.memory[sample_index, :]#通過上一行的index,從relay buffer中提取出這一個batch的記錄b_s = torch.FloatTensor(b_memory[:, :N_STATES])b_a = torch.LongTensor(b_memory[:, N_STATES:N_STATES+1].astype(int))b_r = torch.FloatTensor(b_memory[:, N_STATES+1:N_STATES+2])b_s_ = torch.FloatTensor(b_memory[:, -N_STATES:]) #分別對應(yīng)了這一個batch中的原始狀態(tài),該狀態(tài)采取的動作,該狀態(tài)的reward,該狀態(tài)采取該動作之后的狀態(tài)q_eval = self.eval_net(b_s).gather(1, b_a) # (batch, 1)# self.eval_net(b_s)的輸出是一個(batch,2)的tensor,相應(yīng)的Q(s,a)# 這里gather的操作是根據(jù)b_a是0還是1選擇每一行的0還是1,也就是選擇maxQ(s,a)q_next = self.target_net(b_s_).detach() # detach的作用就是不反向傳播去更新,因為target的更新在前面定義好了的,每100輪更新一次#q_nexts 是Q(s_t+1,a),由于target network不進行更新,所以將q_next detach出來q_target = b_r + GAMMA * q_next.max(1)[0].view(BATCH_SIZE, 1) #r_t+Γ max Q(s_t+1,a)# shape (batch, 1)loss = self.loss_func(q_eval, q_target) self.optimizer.zero_grad()loss.backward()self.optimizer.step() #pytorch老三樣6 使用&訓(xùn)練DQN
dqn = DQN() #創(chuàng)建一個DQN networkprint('\nCollecting experience...') for i_episode in range(400):#采集400個序列s = env.reset() # 重置當前環(huán)境狀態(tài)。#s表示初始化這一個episode的環(huán)境#array([ 2.3993547 , 0.35676894, 0.00279927, -0.2451453 ], dtype=float32)ep_r = 0# ep_r表示每個episode中的rewardfor t in range(1000):#一個epsiode里面有1000步#env.render()#渲染環(huán)境,如果你是再服務(wù)器上跑的,只想出結(jié)果,不想看動態(tài)推桿過程的話,可以注釋掉a = dqn.choose_action(s) #根據(jù)當前的狀態(tài)s,選擇當前回合合適的actions_, r, done, info = env.step(a) # 四個返回的內(nèi)容是state,reward,done(是否重置環(huán)境),infox, x_dot, theta, theta_dot = s_#s的四個狀態(tài) r1 = (env.x_threshold - abs(x)) / env.x_threshold - 0.8# r1代表車的 x水平位移 與 x最大邊距 的距離差的得分r2 = (env.theta_threshold_radians - abs(theta)) / env.theta_threshold_radians - 0.5# r2代表桿的 與垂直線之間的夾角r = r1 + r2 #修改reward,因為如果使用默認的reward的話可能不好訓(xùn)練,所以這里使用了修改后的reward#桿越豎直,越靠近中心,獎勵應(yīng)該越大dqn.store_transition(s, a, r, s_) #狀態(tài),該狀態(tài)使用的action,該狀態(tài)使用這個action之后的獎勵,之后的狀態(tài)#這些信息存儲起來,放入relay buffer中ep_r += r#當前這輪episode的reward++if dqn.memory_counter > MEMORY_CAPACITY:#表明relay buffer中已經(jīng)滿了,也即是已經(jīng)采樣了一些樣本,之后再進行training,那么就可以一邊采樣一邊訓(xùn)練了dqn.learn()if done:print('Ep: ', i_episode, '| Ep_r: ', round(ep_r, 2)) if done:breaks = s_ '''Collecting experience... Ep: 203 | Ep_r: 1.29 Ep: 204 | Ep_r: 1.67 Ep: 205 | Ep_r: 1.36 Ep: 206 | Ep_r: 8.36 Ep: 207 | Ep_r: 3.23 Ep: 208 | Ep_r: 2.25 Ep: 209 | Ep_r: 1.12 Ep: 210 | Ep_r: 1.82 Ep: 211 | Ep_r: 3.1 Ep: 212 | Ep_r: 4.04 Ep: 213 | Ep_r: 1.26 '''loss function 如下:
?
總結(jié)
以上是生活随笔為你收集整理的pytorch 笔记: DQN(experience replay)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 强化学习笔记 experience re
- 下一篇: pytorch 笔记: 协同过滤user