實戰深度強化學習DQN-理論和實踐
1、Q-learning回顧
Q-learning 的 演算法過程如下圖所示:
在Q-learning中,我們維護一張Q值表,表的維數為:狀態數S * 動作數A,表中每個數代表在當前狀態S下可以採用動作A可以獲得的未來收益的折現和。我們不斷的迭代我們的Q值表使其最終收斂,然後根據Q值表我們就可以在每個狀態下選取一個最優策略。
Q值表的更新公式為:
公式中,Q(S,A) 我們可以稱做Q估計值,即我們當前估計的Q值,而:
稱為Q-target,即我們使用貝爾曼方程加貪心策略認為實際應該得到的獎勵,我們的目標就是使我們的Q值不斷的接近Q-target值。
2、深度Q網路(Deep - Q - Network)
2.1 DQN簡介
為什麼會出現DQN呢
在普通的Q-learning中,當狀態和動作空間是離散且維數不高時可使用Q-Table儲存每個狀態動作對的Q值,而當狀態和動作空間是高維連續時,使用Q-Table不現實。
兩篇DQN奠基之作
[1]Playing Atari with Deep Reinforcement Learning
[2]Human-level control through deep reinforcement learning
如何將原始的Q-learning轉換成深度學習問題
將Q-Table的更新問題變成一個函數擬合問題,相近的狀態得到相近的輸出動作。如下式,通過更新參數 θ 使Q函數逼近最優Q值 。因此,DQN就是要設計一個神經網路結構,通過函數來擬合Q值,即:
2.2 DL和RL結合帶來的問題
1、DL需要大量帶標籤的樣本進行監督學習;RL只有reward返回值,而且伴隨著雜訊,延遲(過了幾十毫秒才返回),稀疏(很多State的reward是0)等問題;
2、DL的樣本獨立;RL前後state狀態相關;
3、DL目標分布固定;RL的分布一直變化,比如你玩一個遊戲,一個關卡和下一個關卡的狀態分布是不同的,所以訓練好了前一個關卡,下一個關卡又要重新訓練;
4、過往的研究表明,使用非線性網路表示值函數時出現不穩定等問題。
2.3 DQN解決問題方法
那麼DQN是如何解決上述問題的呢?
1、通過Q-Learning使用reward來構造標籤(對應問題1)
2、通過experience replay(經驗池)的方法來解決相關性及非靜態分布問題(對應問題2、3)
3、使用一個神經網路產生當前Q值,使用另外一個神經網路產生Target Q值(對應問題4)
構造標籤
對於函數優化問題,監督學習的一般方法是先確定Loss Function,然後求梯度,使用隨機梯度下降等方法更新參數。DQN則基於Q-Learning來確定Loss Function。我們想要使q-target值和q-eval值相差越小越好。DQN中的損失函數是:
這裡yi是根據上一個迭代周期或者說target-net網路的參數計算出的q-target值,跟當前網路結構中的參數無關,yi的計算如下:
這樣,整個目標函數就可以通過隨機梯度下降方法來進行優化:
經驗回放
經驗池的功能主要是解決相關性及非靜態分布問題。具體做法是把每個時間步agent與環境交互得到的轉移樣本 (st,at,rt,st+1) 儲存到回放記憶單元,要訓練時就隨機拿出一些(minibatch)來訓練。(其實就是將遊戲的過程打成碎片存儲,訓練時隨機抽取就避免了相關性問題)
雙網路結構
在Nature 2015版本的DQN中提出了這個改進,使用另一個網路(這裡稱為target_net)產生Target Q值。具體地,Q(s,a;θi) 表示當前網路eval_net的輸出,用來評估當前狀態動作對的值函數;Q(s,a;θ?i) 表示target_net的輸出,代入上面求 TargetQ 值的公式中得到目標Q值。根據上面的Loss Function更新eval_net的參數,每經過N輪迭代,將MainNet的參數複製給target_net。
引入target_net後,再一段時間裡目標Q值使保持不變的,一定程度降低了當前Q值和目標Q值的相關性,提高了演算法穩定性。
2.4 DQN演算法流程
NIPS 2013版
Nature 2015版
可以看到,兩版的DQN都使用了經驗池,而2015版的DQN增加了target-net,提高了演算法穩定性。
3、DQN實現DEMO
找了很多DQN的例子,有原版的實現Atari的,也有Flappy Bird的,但是最簡單的還是莫煩大神的Demo,github地址是:https://github.com/MorvanZhou/Reinforcement-learning-with-tensorflow。
在介紹整個Demo前,我們介紹兩種DQN的實現方式,一種是將s和a輸入到網路,得到q值,另一種是只將s輸入到網路,輸出為s和每個a結合的q值。這裡莫煩大神的代碼採取了後一種方式。
如果你對DQN的原理有比較深刻的認識,那麼讀莫煩大神的代碼也並不是十分困難。這裡我們想要實現的效果類似於尋寶。
其中,紅色的方塊代表尋寶人,黑色的方塊代表陷阱,黃色的方塊代表寶藏,我們的目標就是讓尋寶人找到最終的寶藏。
這裡,我們的狀態可以用橫縱坐標表示,而動作有上下左右四個動作。使用tkinter來做這樣一個動畫效果。寶藏的獎勵是1,陷阱的獎勵是-1,而其他時候的獎勵都為0。
接下來,我們重點看一下我們DQN相關的代碼。
定義相關輸入
這了,我們用s代表當前狀態,用a代表當前狀態下採取的動作,r代表獲得的獎勵,s_代表轉移後的狀態。
經驗池
雙網路結構
target_net和eval_net的網路結構必須保持一致,這裡我們使用的是兩層全鏈接的神經網路,值得注意的一點是對於eval_net來說,網路的輸入是當前的狀態s,而對target_net網路來說,網路的輸入是下一個狀態s_,因為target_net的輸出要根據貝爾曼公式計算q-target值,即
代碼如下:
每隔一定的步數,我們就要將target_net中的參數複製到eval_net中:
計算損失並優化
首先,對於eval_net來說,我們只要得到當前的網路輸出即可,但是我們定義的網路輸出是四個動作對應的q-eval值,我們要根據實際的a來選擇對應的q-eval值,這一部分的代碼如下:
中間有幾個函數不太了解的,上面都有詳細的注釋,如果還不是很理解的話,大家可以百度或者閱讀相應函數的源碼。
對於target_net網路來說,我們要根據下面的式子來計算q-target值:
第一部分的R我們是已經得到了的,剩下的就是根據貪心策略選擇四個輸出中最大的一個即可:
接下來,我們就可以定義我們的損失函數並選擇優化器進行優化:
網路的訓練
每隔一定的步數,我們就要將eval_net中的參數複製到target_net中,同時我們要從經驗池中選擇batch大小的數據輸入到網路中進行訓練。
剩下的代碼就不介紹啦,大家不妨去github上fork大神的代碼,跟著進行練習,相信會對DQN的原理有一個更進一步的認識。
4、參考文獻
1、深度強化學習——DQN:http://blog.csdn.net/u013236946/article/details/72871858
2、莫煩的github:https://github.com/MorvanZhou/Reinforcement-learning-with-tensorflow
TAG:小小挖掘機 |