【强化学习】Policy Gradient(策略梯度)算法详解
1 Policy Gradient簡介
1.1 基于策略和基于值的強化學習方法不同
強化學習是一個通過獎懲來學習正確行為的機制。家族中有很多種不一樣的成員,有學習獎懲值,根據自己認為的高價值選行為,比如Q-Learning,Deep-Q-network,也有不通過分析獎懲值,直接輸出行為的方法,這就是今天要說的Policy Gradient加上一個神經網絡來輸出預測的動作。對比起以值為基礎的方法,Policy Gradient直接輸出動作的最大好處就是,他能在一個連續區間內挑選動作,而基于值的,比如Q-Learning,它如果在無窮多得動作種計算價值,從而選擇行為,這他可吃不消。
1.2 算法更新
有了神經網絡當然方便,但是,我們怎么進行神經網絡的誤差反向傳遞呢?Policy Gradient的誤差又是什么呢?答案是沒有誤差。但是他的確是在進行某一種的反向傳遞。這種反向傳遞的目的是讓這次被選中的行為更有可能在下次發生。但是我們要怎么確定這個行為是不是應當被增加被選的概率呢?這時候,reward獎懲正可以在這個時候排上用場。
1.3 具體更新步驟
現在演示一遍,觀測的信息通過神經網絡分析,選出了左邊的行為,我們直接進行反向傳遞,使之下次被選的可能性增加,但是獎懲信息卻告訴我們,這次的行為是不好的,那我們的動作可能性增加的幅度隨之被減低。這樣就能靠獎勵來左右我們的神經網絡反向傳遞。我們再舉一個例子,假如這次的觀測信息讓神經網絡選擇了右邊的行為,右邊的行為隨之想要進行反向傳遞,使右邊的行為下次被多選一點,這時,獎懲信息也來了,告訴我們這是好行為,那我們就在這次反向傳遞的時候加大力度,讓他下次被多選的幅度更猛烈。這就是Policy Gradient的核心思想。
2 Policy Gradient算法更新
全部代碼免費下載地址如下:
https://download.csdn.net/download/shoppingend/85194070
2.1 要點
Policy Gradient是RL中一個大家族,他不像Value-based方法(Q-Learning,Sarsa),但他也要接收環境信息(observation),不同的是他要輸出不是action的value,而是具體的那一個action,這樣Policy Gradient就跳過了value這個階段。而且Policy Gradient最大的一個優勢是:輸出的這個action可以是一個連續的值,之前我們說到的value-based方法輸出的都是不連續的值,然后再選擇值最大的action。而Policy Gradient可以在一個連續分布上選取action。
2.2 算法
我們介紹最簡單的Policy Gradient算法是一種基于整條回合數據的更新,也叫REINFORCE方法。這種方法是Policy Gradient的最基本方法,有了這個的基礎,我們再來做更高級的。
Δ(log(Policy(s,a))*V表示在狀態s對所選動作a的吃驚度,如果Policy(s,a)概率越小,反向的log(Policy(s,a))(即-log§)反而越大。如果在Policy(s,a)很小的情況下,拿到了一個大的R,也就是大的V,那-Δ(log(Policy(s,a))*V就更大,表示更吃驚,(我選了一個不常選的動作,卻發現原來它能得到了一個好的reward,那我就得對我這次的參數進行一個大幅修改)。這就是吃驚度的物理意義了。
2.3 算法代碼形成
先定義主更新的循環:
import gym from RL_brain import PolicyGradient import matplotlib.pyplot as pltRENDER = False # 在屏幕上顯示模擬窗口會拖慢運行速度, 我們等計算機學得差不多了再顯示模擬 DISPLAY_REWARD_THRESHOLD = 400 # 當 回合總 reward 大于 400 時顯示模擬窗口env = gym.make('CartPole-v0') # CartPole 這個模擬 env = env.unwrapped # 取消限制 env.seed(1) # 普通的 Policy gradient 方法, 使得回合的 variance 比較大, 所以我們選了一個好點的隨機種子print(env.action_space) # 顯示可用 action print(env.observation_space) # 顯示可用 state 的 observation print(env.observation_space.high) # 顯示 observation 最高值 print(env.observation_space.low) # 顯示 observation 最低值# 定義 RL = PolicyGradient(n_actions=env.action_space.n,n_features=env.observation_space.shape[0],learning_rate=0.02,reward_decay=0.99, # gamma# output_graph=True, # 輸出 tensorboard 文件 )主循環:
for i_episode in range(3000):observation = env.reset()while True:if RENDER: env.render()action = RL.choose_action(observation)observation_, reward, done, info = env.step(action)RL.store_transition(observation, action, reward) # 存儲這一回合的 transitionif done:ep_rs_sum = sum(RL.ep_rs)if 'running_reward' not in globals():running_reward = ep_rs_sumelse:running_reward = running_reward * 0.99 + ep_rs_sum * 0.01if running_reward > DISPLAY_REWARD_THRESHOLD: RENDER = True # 判斷是否顯示模擬print("episode:", i_episode, " reward:", int(running_reward))vt = RL.learn() # 學習, 輸出 vt, 我們下節課講這個 vt 的作用if i_episode == 0:plt.plot(vt) # plot 這個回合的 vtplt.xlabel('episode steps')plt.ylabel('normalized state-action value')plt.show()breakobservation = observation_3 Policy Gradient思維決策
3.1 代碼主結構
用基本的 Policy gradient 算法,和之前的 value-based 算法看上去很類似。
class PolicyGradient:# 初始化 (有改變)def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):# 建立 policy gradient 神經網絡 (有改變)def _build_net(self):# 選行為 (有改變)def choose_action(self, observation):# 存儲回合 transition (有改變)def store_transition(self, s, a, r):# 學習更新參數 (有改變)def learn(self, s, a, r, s_):# 衰減回合的 reward (新內容)def _discount_and_norm_rewards(self):初始化:
class PolicyGradient:def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):self.n_actions = n_actionsself.n_features = n_featuresself.lr = learning_rate # 學習率self.gamma = reward_decay # reward 遞減率self.ep_obs, self.ep_as, self.ep_rs = [], [], [] # 這是我們存儲 回合信息的 listself._build_net() # 建立 policy 神經網絡self.sess = tf.Session()if output_graph: # 是否輸出 tensorboard 文件# $ tensorboard --logdir=logs# http://0.0.0.0:6006/# tf.train.SummaryWriter soon be deprecated, use followingtf.summary.FileWriter("logs/", self.sess.graph)self.sess.run(tf.global_variables_initializer())3.2 建立Policy神經網絡
這次我們要建立的神經網絡是這樣的:
因為這是強化學習,所以神經網絡中沒有監督學習中的y label。取而代之的是我們選的action。
為什么使用loss=-log(prob)*Vt當作loss。簡單來說,上面提到了兩種行式來計算neg_log_prob,這兩種行式是一摸一樣的,只是第二個是第一個的展開行式。如果仔細看第一個行式,就是在神經網絡分類問題中的cross-entropy。使用softmax和神經網絡的參數按照這個真實標簽改進。這顯然和一個分類問題沒有太多的區別,我們能將這個neg_log_prob理解成cross-entropy的分類誤差。分類問題中的標簽是真實x對應的y,而我們Policy Gradient中,x是state,y就是它按照這個x所做的動作號碼。所以也可以理解成,它按照x做的動作永遠是對的(出來的動作永遠是正確標簽,他也永遠會按照這個正確標簽修改自己的參數。可是事實并不是這樣,他的動作不一定都是正確標簽,這就是強化學習(Policy Gradient)和監督學習(classification)的區別。
為了確保這個動作是正確標簽,我們的loss在原本的cross-entropy行式上乘以Vt,用Vt來告訴這個cross-entropy算出來的梯度是不是一個值得信賴的梯度。如果Vt小,或者是負的,就說明這個梯度下降是一個錯誤的方向,我們應該向著另一個方向更新參數,如果這個Vt是正的,或很大,Vt就會稱贊cross-entropy出來的梯度,并朝著這個方向梯度下降。下面有一張圖,也正是闡述的這個思想。
而為什么是loss=-log(prob)Vt而不是loss=-probVt。原因是這里的prob是從softmax出來的,而計算神經網絡里的所有參數梯度,使用到的就是cross-entropy,然后將這個梯度乘以Vt來控制梯度下降的方向和力度。
3.3 選行為
這個行為不再是用Q-value來選定的,而是用概率來決定。即使不用epsilon-greedy,也具有一定的隨機性。
class PolicyGradient:def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):...def _build_net(self):...def choose_action(self, observation):prob_weights = self.sess.run(self.all_act_prob, feed_dict={self.tf_obs: observation[np.newaxis, :]}) # 所有 action 的概率action = np.random.choice(range(prob_weights.shape[1]), p=prob_weights.ravel()) # 根據概率來選 actionreturn action3.4 存儲回合
這一部分就是將這一步的observation,action,reward加到列表中去。因為本回合完畢之后要清空列表,然后存儲下一回合的數據,所以我們會在learn()當中進行清空列表的動作
class PolicyGradient:def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):...def _build_net(self):...def choose_action(self, observation):...def store_transition(self, s, a, r):self.ep_obs.append(s)self.ep_as.append(a)self.ep_rs.append(r)3.5 學習
本節的learn()很簡單首先我們要對這回合的所有的reawrd動動手腳,使得它變得更適合被學習。第一就是隨著時間推進,用γ衰減未來的reward,然后為了一定程度上減小Policy Gradient回合variance。
class PolicyGradient:def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):...def _build_net(self):...def choose_action(self, observation):...def store_transition(self, s, a, r):...def learn(self):# 衰減, 并標準化這回合的 rewarddiscounted_ep_rs_norm = self._discount_and_norm_rewards() # 功能再面# train on episodeself.sess.run(self.train_op, feed_dict={self.tf_obs: np.vstack(self.ep_obs), # shape=[None, n_obs]self.tf_acts: np.array(self.ep_as), # shape=[None, ]self.tf_vt: discounted_ep_rs_norm, # shape=[None, ]})self.ep_obs, self.ep_as, self.ep_rs = [], [], [] # 清空回合 datareturn discounted_ep_rs_norm # 返回這一回合的 state-action value再看discounted_ep_rs_norm
vt = RL.learn() # 學習, 輸出 vt, 我們下節課講這個 vt 的作用if i_episode == 0:plt.plot(vt) # plot 這個回合的 vtplt.xlabel('episode steps')plt.ylabel('normalized state-action value')plt.show()最后使如何用算法實現對未來reward的衰減
class PolicyGradient:def __init__(self, n_actions, n_features, learning_rate=0.01, reward_decay=0.95, output_graph=False):...def _build_net(self):...def choose_action(self, observation):...def store_transition(self, s, a, r):...def learn(self):...def _discount_and_norm_rewards(self):# discount episode rewardsdiscounted_ep_rs = np.zeros_like(self.ep_rs)running_add = 0for t in reversed(range(0, len(self.ep_rs))):running_add = running_add * self.gamma + self.ep_rs[t]discounted_ep_rs[t] = running_add# normalize episode rewardsdiscounted_ep_rs -= np.mean(discounted_ep_rs)discounted_ep_rs /= np.std(discounted_ep_rs)return discounted_ep_rs總結
以上是生活随笔為你收集整理的【强化学习】Policy Gradient(策略梯度)算法详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Unity 集成admob 出错AAPT
- 下一篇: 汽车电子行业入门指南「主要国内新能源车销