用Gym學習強化學習之Policy Gradient

用Gym學習強化學習之Policy Gradient

來自專欄 Way to NLP12 人贊了文章

作者:Cloudyyy@HIT

興趣方向:自然語言處理、人工智慧


目錄

  • 什麼是強化學習
  • 強化學習的問題要素
  • Gym簡介
  • Policy Gradient實戰
  • 總結
  • 參考

1 什麼是強化學習

強化學習在機器學習的應用分類里常常和監督學習非監督學習並列。

監督學習非監督學習中,我們可以獲得固定的數據集,將數據集餵給特定的模型,擬合數學公式,學習其特徵規律。

監督學習 VS 非監督學習

在上述問題中,我們需要考慮的問題是如何將已有數據集的知識遷移到新的數據集中。

然而,強化學習並不屬於這類問題。在強化學習里,我們沒有現成的數據集可以學習,而是需要在環境中「試錯」,根據環境給我們的反饋進行模型參數的調整。

所以,反饋即是強化學習獨特的問題特徵。

2 強化學習的問題要素

在強化學習中,三個重要的要素是:Actor(Agent)、Environment、Reward

這三者的關係可以表示為:

Agent是我們學習的對象,Agent可以做出自己的行為action,然後獲取Environment反饋的信息observation(state)。根據observation(state)附帶的激勵reward,Agent可以判斷本次action的好壞,進而調整自己的參數。同時,本次observation(state)將繼續作為Agent的輸入進行下一次行為action的判斷。

這種根據環境反饋來進行模型學習的方式就是強化學習。

3 Gym簡介

聽完上面的描述,讀者可能對強化學習還存在較為模糊的認知,這裡選擇Gym平台來讓大家直觀感受強化學習的訓練過程。

Gym 環境示意

Gym是Openai開發的一個用來測試強化學習演算法的工具。當我們使用Gym的時候,我們只需要重點關注Agent的訓練過程,而Environment、reward這些信息都將由Gym平台提供,無需我們進行額外的設計和開發。

這裡我們選擇較為簡單的CartPole-v1進行強化學習演算法Policy Gradient的實現:

在這個任務中,小車Cart通過左移和右移來保證竿子Pole的平衡,時間越久獎勵reward越高。

在使用前,請根據官方文檔安裝其Gym,本文選擇的工具為Python 3.6,Pytorch 0.4

4 Policy Gradient實戰

在Policy Gradient中,我們需要訓練一個Agent。這個Agent相當於一個分類器,其輸入是觀測到環境的信息observation(state),輸出為行為action的概率分布。我們可以用簡單的多層感知機去實現這個分類器:

在該任務中,可以查看輸入observation(state)和輸出action的維度:

import gymenv = gym.make(CartPole-v1)print(env.action_space)# Discrete(2)print(env.observation_space)# Box(4,)

我們可以構建一個簡單的多層感知機充當二分類器:

class PGN(nn.Module): def __init__(self): super(PGN, self).__init__() self.linear1 = nn.Linear(4, 24) self.linear2 = nn.Linear(24, 36) self.linear3 = nn.Linear(36, 1) def forward(self, x): x = F.relu(self.linear1(x)) x = F.relu(self.linear2(x)) x = torch.sigmoid(self.linear3(x)) return x

我們的需要訓練一個CartAgent,應當至少具備以下介面:

class CartAgent(object): def __init__(self, learning_rate, gamma): self.pgn = PGN() self.gamma = gamma self._init_memory() self.optimizer = torch.optim.RMSprop(self.pgn.parameters(), lr=learning_rate) def memorize(self, state, action, reward): # save to memory for mini-batch gradient descent self.state_pool.append(state) self.action_pool.append(action) self.reward_pool.append(reward) self.steps += 1 def learn(self): pass def act(self, state): return self.pgn(state)

前面提過,強化學習不同於監督學習(能夠直接使用訓練語料中的X和Y擬合該模型)。在Policy Gradient中,我們需要使用特殊的損失函數:

其中 p(a|s) 由Agent模型計算得出,R 即Reward,由環境給出。這個損失函數能夠提高reward值大的action出現的概率。loss的核心實現為:

def learn(self): self._adjust_reward() # policy gradient self.optimizer.zero_grad() for i in range(self.steps): # all steps in multi games state = self.state_pool[i] action = torch.FloatTensor([self.action_pool[i]]) reward = self.reward_pool[i] probs = self.act(state) m = Bernoulli(probs) loss = -m.log_prob(action) * reward loss.backward() self.optimizer.step() self._init_memory()

想要讓該損失函數得到訓練,我們就必須獲得多組state,action,reward。在實際應用中,這樣的組合需要我們在遊戲過程中隨機抽樣出來。

對於某次遊戲,我們可以抽樣出多組state、action、reward:

具體的實現為:

# hyper parameterBATCH_SIZE = 5LEARNING_RATE = 0.01GAMMA = 0.99NUM_EPISODES = 500env = gym.make(CartPole-v1)cart_agent = CartAgent(learning_rate=LEARNING_RATE, gamma=GAMMA)for i_episode in range(NUM_EPISODES): next_state = env.reset() env.render(mode=rgb_array) for t in count(): state = torch.from_numpy(next_state).float() probs = cart_agent.act(state) m = Bernoulli(probs) action = m.sample() action = action.data.numpy().astype(int).item() next_state, reward, done, _ = env.step(action) env.render(mode=rgb_array) # end actions reward equals 0 if done: reward = 0 cart_agent.memorize(state, action, reward) if done: logger.info({Episode {}: durations {}.format(i_episode, t)}) break # update parameter every batch size if i_episode > 0 and i_episode % BATCH_SIZE == 0: cart_agent.learn()

上述state、action、reward組合存在一定的問題。在這個遊戲中所有的reward均為0或1,但是某次遊戲實際進行了多輪,某次action產生的效益可能遠遠大於其他相同reward的action。因此,我們需要在某次遊戲中結合整個馬爾科夫鏈去考慮某次action的潛在reward

一種很容易想到的思路是,如果某次action之後的reward很大,說明這次action更好,我們可以將這種潛在的reward添加進來:

def _adjust_reward(self): # backward weight running_add = 0 for i in reversed(range(self.steps)): if self.reward_pool[i] == 0: running_add = 0 else: running_add = running_add * self.gamma + self.reward_pool[i] self.reward_pool[i] = running_add

此外,我們需要reward進行適當的均一化。如果reward均為正,則在抽樣過程中可能會讓一些本應當降低概率的action獲得更大的概率提升;如果reward沒有進行平均,則遊戲行為更多的action組傾向於獲得更大的概率提升。

# normalize reward reward_mean = np.mean(self.reward_pool) reward_std = np.std(self.reward_pool) for i in range(self.steps): self.reward_pool[i] = (self.reward_pool[i] - reward_mean) / reward_std

完成代碼後,可以看到實驗結果。在起初的時候,小車只能堅持較短的時間:

進行150次遊戲後,小車堅持的時間已經有了顯著的提高。

完全版的Demo在這裡:github.com/cloudyyyyy/pytorch-rl-demo。

5 總結

從實踐結果看,實現一個Demo級別的Policy Gradient演算法就可以取得較好的效果。如果你想學習強化學習演算法,Gym將會是一個測試這些演算法的好幫手。

6 參考

  1. Gym: A toolkit for developing and comparing reinforcement learning algorithms
  2. 台灣大學-李宏毅《Deep Reinforcement Learning》
  3. Reinforcement Learning (DQN) tutorial
  4. Finspire13/pytorch-policy-gradient-example

推薦閱讀:

實現端到端的物體分割訓練
搭建模型第一步:你需要預習的NumPy基礎都在這了
怎樣應對人工智慧帶來的倫理問題
中荷兩國戰略合作進一步平穩落地,國民用藥安全保障性升級
中興視覺大數據報:人工智慧技術能夠為家庭帶來全新的體驗

TAG:強化學習ReinforcementLearning | OpenAI | 人工智慧 |