深度強化學習——Policy Gradient 玩轉 CartPole 遊戲

Image from unsplash.com by helloquence

前面的文章我們介紹了 Q-learning, DQN 等方法都是基於價值的強化學習方法,今天我們介紹的 Policy Gradient 方法是基於策略的強化學習方法。該方法的理論部分已經介紹過了,這裏就不贅述了,直接上手項目。

本文的全部代碼可在我的 github repo 中查看

https://github.com/zht007/tensorflow-practice

1. 監督學習回顧

爲了更好地理解 Policy Gradient 算法,我們用監督學習的分類問題作爲類比。

以手寫數字識別的項目爲例,:

  1. 將圖片作爲輸入傳給神經網絡。
  2. 神經網絡會給該圖片屬於哪一類(數字 0 到 9)給出一個評分(logits)。
  3. 評分(logits)通過 Softmax 就可以轉換爲屬於每一類(數字 0 到 9)的概率(Probability)。
  4. 通過 Cross Entropy (交叉商) 對比與真實標籤的“距離
  5. 最後這個“距離” 就作爲loss function (損失函數) 反向傳回神經網絡進行參數更新。

Image from github repo with Apache-2.0 license

如上圖所示 Cross entropy 的公式如下
-\sum Y_{i}^{\prime} \cdot \log \left(Y_{i}\right)

2. Policy 梯度上升

在強化學習中,我們用神經網絡來參數化策略,神經網絡扮演策略的角色,在神經網絡輸入狀態,就可以輸出策略價值函數,指導智能體的行動。我們在之前的文章中講到,優化策略函數(神經網絡)的過程可以利用用梯度上升(Gradient Ascent)的方法,以獲取最價值。然而目標函數的策略梯度與 Cross entropy 非常相似:

定理:對於任何可微的策略π(s,a),對於任何策略的目標函數J(θ)策略梯度都是:
\nabla_{\theta} J(\theta)=\mathbb{E}_{\pi_{\theta}}\left[\nabla_{\theta} \log \pi_{\theta}(s, a) Q^{\pi_{\theta}}(s, a)\right]

如果 Q(s, a) 作爲“標籤”的話,上面的公式與 Cross Entropy 公式僅相差一個負號,這個負號的作用恰好可以將反向傳播的梯度下降,轉換成我們需要的梯度上升。

當然如果覺得這個理論理解起來比較困難,我還有一個更加簡單的角度,我們是這樣操作的:

  • 首先,我們採用蒙特卡洛的方法完成一個完整的 episode 記錄其中每一個[s, a, r]:

\left\{s_{1}, a_{1}, r_{2}, \dots, s_{T-1}, a_{T-1}, r_{T}\right\} \sim \pi_{\theta}

  • 然後,將 s1, s2, ... sT 帶入神經網絡,預測得到每一個狀態下的行動概率。將實際行動作爲“標籤”帶入 corss entropy 的公式。但是這個“標籤” 並不是真正的標籤,並不能指導神經網絡朝正確的方向更新。我們需要乘以獎勵r,獎勵r 的作用相當於對“標籤”的評價,獎勵越大神經網絡就朝着“標籤”的方向更新,反之就向相反的方向更新。

  • 最後,我們再講這個新的函數作爲 loss fuction 傳給神經網絡進行更新。

Image from github repo with Apache-2.0 license

最後,還需要注意的是,這裏的獎勵 R 即 r1, r2, ... rT 在送入上式進行反向傳播之前是需要進行,discount 和 normalize 兩步處理。discount 很好理解,即離結束越遠的獎勵需要 discount 越多,離結束回合越近需要 discount 越少。同時,normalize 的目的是爲了鼓勵那些正確地動作,因爲特別是在遊戲初期,在大多數的隨機行動中,正確步伐所獲得的獎勵往往會容易被淹沒在衆多的隨機行動所帶來的獎勵了。

3. Tensorflow 代碼實踐

關於 CartPole 的遊戲之前已經介紹夠多了,初始化就不多說了,與之前相似。重點是構建 PGAgent 對象。

3.1 Agent 神經網絡大腦

對於神經網絡,self.states, self.actions 和 self.discounted_episode_rewards 即前面介紹的輸入,“標籤”,和處理後的獎勵。self.sample_op 的作用是根據概率選擇行動

def _build_net(self):
    self.states = tf.placeholder(tf.float32, [None,OBSERVATION_SPACE_SIZE])
    self.actions = tf.placeholder(tf.int32, [None,])
    self.discounted_episode_rewards = tf.placeholder(tf.float32, [None,])

    fc1 = tf.layers.dense(
        inputs = self.states,
        units = 10,
        activation = tf.nn.relu,
        kernel_initializer=tf.random_normal_initializer(mean=0, stddev=0.3),
        bias_initializer=tf.constant_initializer(0.1)
    )
    
    act_logits = tf.layers.dense(
        inputs = fc1,
        units = ACTION_SPACE_SIZE,
        kernel_initializer=tf.random_normal_initializer(mean=0, stddev=0.3),
        bias_initializer=tf.constant_initializer(0.1),
    )

    self.actions_prob = tf.nn.softmax(act_logits)
    
    #sample an action from predicted probabilities    
    self.sample_op = tf.multinomial(logits=act_logits, num_samples=1)

    neg_log_prob = tf.reduce_sum(-tf.log(self.actions_prob) * tf.one_hot(self.actions, ACTION_SPACE_SIZE),axis =1)
    loss = tf.reduce_mean(neg_log_prob * self.discounted_episode_rewards)

    self.train_op = tf.train.AdamOptimizer(0.001).minimize(loss)

Code from github repo with MIT license

3.2 Discount and Normalize Rewards

正如之前提到的,Rewards需要經過 discount 和 normalize 兩個步驟,函數如下:

  def discount_rewards(self, rewards):
    discount_rewards = np.zeros_like(rewards)
    running_add = 0
    for t in reversed(range(len(rewards))):
      running_add = running_add * GAMMA + rewards[t]
      discount_rewards[t] = running_add

      mean = np.mean(discount_rewards)
      std = np.std(discount_rewards)
      discount_rewards = (discount_rewards - mean)/std

      return discount_rewards

3.4 訓練過程

訓練過程分爲三個步驟

首先,初始化每個episode (回合) 的 states, actions 和 rewards。

    episode_states, episode_actions, episode_rewards = [],[],[] 
    #Reset single step reward
    episode_reward = 0

然後, 通過agent 的“大腦“ 選擇行動得到該行動的 state, action 和 reward

              action = agent.choose_action(current_state)
        next_state, reward, done, _ = env.step(action)

接着,將s, a 和 r 收集到 states, actions 和 rewards 中

        episode_states.append(current_state)
        episode_actions.append(action)
        episode_rewards.append(reward)

最後,將收集到的 states, actions 和 rewards 傳回 agent “大腦” 進行學習

agent.train(np.vstack(episode_states), np.array(episode_actions), np.array(episode_rewards))

Code from github repo with MIT license

3.5 訓練結果

Policy Gradient 的訓練時間還是蠻久的,經過30000 個回合的訓練,最大,平均和最小獎勵都在穩步上升。對於最大獎勵在5000 個回合之後獎勵就基本穩定在最大獎勵200了,平均獎勵和最小獎勵在訓練過程中都有上下起伏,但是總體上是在收斂和上升的。

Image crested by @hongtao

4. 總結

本文介紹的 Policy Gradient 方法是深度學習與強化學習結合的一個非常典型的案例,由於跟監督學習非常相似,所以比起 Q-learning 來說更加容易理解。Policy Gradient 作爲基於策略的強化學習方法如何與基於價值的Q learning 相結合呢? 這將是我們接下來研究的問題。


參考資料

[1] Reinforcement Learning: An Introduction (2nd Edition)
[2] David Silver's Reinforcement Learning Course (UCL, 2015)
[3] Github repo: Reinforcement Learning


相關文章

強化學習——MC(蒙特卡洛)玩21點撲克遊戲
強化學習實戰——動態規劃(DP)求最優MDP
強化學習——強化學習的算法分類
強化學習——重拾強化學習的核心概念
AI學習筆記——Sarsa算法
AI學習筆記——Q Learning
AI學習筆記——動態規劃(Dynamic Programming)解決MDP(1)
AI學習筆記——動態規劃(Dynamic Programming)解決MDP(2)
AI學習筆記——MDP(Markov Decision Processes馬可夫決策過程)簡介
AI學習筆記——求解最優MDP


首發steemit

歡迎掃描二維碼關注我的微信公衆號“tensorflow機器學習”,一起學習,共同進步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章