文章首發于 huangyz.name, 純屬原創,轉載請注明來源。
歡迎大家 Follow Github: huangyz0918
本文目錄
- 前言
- DRL 中的 Policy Gradient
-
更精準的 Reward Function
- 改進的
- 添加 Baseline
- 改進的
-
On-Policy 到 Off-Policy
- On-Policy 學習方式
- Important Sampling
- Proximal Policy Optimization (PPO)
- Trust Region Policy Optimization (TRPO)
- PPO2
-
Q-Learning
- Monte-Carlo (MC) 和 Temporal-difference (TD)
- State-action Value Function
- Target Network
- Exploitation 和 Exploration
- Reply Buffer
前言
最近因為項目和論文的關系需要用到一些 Deep Reinforcement Learning 的知識,于是快速把 DRL 的一些基本算法和思想過了一遍(參考了李宏毅教授的強化學習課程)。之前趕時間寥寥草草地寫了七八頁紙,現在因為 COVID-19 導致各種 DDL 推遲了以后便有了一些空閑時間,覺得還是記錄在博客比較好。個人覺得 RL 這個東西思想是很精妙的,但如果只是要了解一些比較粗淺的東西,學習成本很低,完全可以幾天內掌握個大概。
由于我比較懶,這篇博客主要是寫給自己看的,可能有些地方不會解釋得太清楚 : )
DRL 中的 Policy Gradient
強化學習實際上是一個機器與環境不斷互動和學習的過程,其中包括幾個重要的組成部分:
-
Agent
: 與環境互動的智能體 -
Environment
: 與智能體交互的環境 -
Reward Function
: 環境給予智能體反饋的方式
舉個例子,比如使用強化學習玩游戲,那么理論上的一個流程就是:
- 初始化一個 agent
- agent 接收環境所給的第一個界面,也是輸入第一個 state:
- agent 給出一個對應的反應:
- 環境接收
給出對應的
重復上述流程直到游戲結束。
我們認為從游戲開始到游戲結束是一個 episode,用 表示。然后在這個玩游戲的過程中,舉個例子:假設這個游戲是我們熟知的雷電(飛機大戰游戲),用戶需要操作飛機左右移動以避開飛來的隕石等障礙,同時又要主動出擊才能獲得比較高的分數。我方戰斗機便可以看作強化學習中的 agent,周圍的隕石,敵機等無法控制(含有隨機性)的東西就是與我們 agent 交互的環境。
為了讓我們的 agent 在玩游戲的過程中逐漸掌握游戲的技巧,我們需要設計 reward function, 也就是設計一個反饋機制。其實游戲本身是含有這樣的反饋機制的,比如擊落一架敵方戰斗機可以獲得多少分,吃到補給可以獲得多少分,被子彈擊中扣多少分這樣。agent 做出的每一步,或多或少都在改變著最終的游戲結果。
我們把整個 episode 最終獲得的分數用 reward function 表示為:
深度強化學習,之所以稱為深度強化學習,是因為我們的 agent 實際上是一個 DNN,給定某個 state 輸入,針對這個輸入輸出對應的 action,學習的過程實際上就是在 update 這個 DNN 的參數,使得最終一個 episode 下來全局的 reward function 可以達到最大值。
其中,我們把一個 agent 進行玩游戲的策略稱為一個 policy, 用 表示,不同的
表示不同的游戲策略(不同的 agent), 我們要做的就是求給定
的
的最大值, 這里我們可以用梯度增加的方式計算:
為了準確更新神經網絡的參數,我們需要盡可能多的獲取一些游戲數據,在一個相同的 policy 下,我們可能會進行非常多場游戲,所以計算多場游戲的平均 reward 就是:
對 求梯度:
為了方便實現最終將式子寫成了上述形式,其中 是第 n 個 episode 的 reward 總和,
代表的意思是在第 n 個 episode 里面,總共有
個 step (一個 step 定義為給定一個 state s, agent 做出一個反應 a)。
這個式子是非常好理解的,為了讓最終的 policy gradient 有最大值,當某個 step 發生的那個 中有相對較大的
,我們就要增加其出現的概率,反之,如果 reward 的值太小我們就要減小這個操作所出現的概率。
上述公式中用了一個近似,在給定分布求期望的過程中:
這里的 N 越大,實際上相當于在 p(x) 分布上 sample 到的值越多,結果也就越接近。
另外一個小技巧是:
我們可以通過分子分母同時乘上一個 將
中梯度運算中拿出來:
更精準的 Reward Function
改進的
在上述公式中,實際上存在著一些問題,其中最大的問題就是:該如何定義我們的 reward function ?如果僅僅是按照游戲的規則來,
是游戲中的每一步所產生的 reward 在整場游戲中的累加,在式子中:
有些 action 是好的,有的是不好的,但是所有的 action 的概率前面都會被乘上同樣的 weight: ,顯然是不合理的。
那么如果我在給定某個 后 agent 輸出了
,實際上它并不會影響到
之前的那些情況,在
發生之前的 reward 實際上是和
無關的。
舉個例子,一個簡單的游戲我們玩了兩場:
State | |||
---|---|---|---|
Action | |||
Reward | +10 | +0 | -6 |
State | |||
---|---|---|---|
Action | |||
Reward | -5 | +0 | -6 |
那么 在第一種游戲情況上就會被增加出現的概率 (乘上 4),而在第二種情況下同樣的場景和操作就會被降低概率 (乘上 -11),這是不科學的,第二場游戲之所以不好,是因為在
之前的
產生了 -5 的 reward,這個實際上和
是無關的。但是
之后的是和它有關的,
可能正是要發生在
之后才會帶來 -6 的 reward。
所以我們可以使用某個特定的 之后的所有 reward 總和來代表
的 reward,而不是全部 reward 的總和。為了表示計算 reward 的方法,我們引入 advantage function:
,在此之前
。
我們把改進的 reward 計算式 代入
得到
另外,我們可以給 加上一個影響力衰弱參數
,因為時間拖得越長,越前面發生的事件對后來的影響就會越小:
添加 Baseline
有些游戲中,游戲者無論采取何種 action,reward 可能的情況全都是正的,這個從理論上來說并不會出現問題。但是在 sample 數據的時候,如果 sample 的數量不夠多,沒被 sample 到的 action 保持不變,但是被 sample 到的所有 action 都會相應的增大,在 normalize 之后未被 sample 到的 action 對應的概率就減小了,但是我們能說沒被 sample 到的 action 就不是好的 action 嗎?
很顯然不能,所以這里又有一個小的 tip:減去一個 baseline 使得 的值有正有負 ,一般來說這個 baseline 就是所有 reward 的期望:
代入得:
結合上面的優化方法:
On-Policy 到 Off-Policy
On-Policy 學習方式
理解了上述原理,之后要做的無非就是更新神經網絡,on-policy 的意思就是:與環境交互學習的 agent 和被動更新的 agent 是同一個。具體的流程可以表示為:
- agent 先初始化,并且與環境做互動
- 在互動的過程中我們 sample 一定數量 (m) 的數據
- 在積累了 m 個
的數據以后,我們用這么多數據去 update agent policy
- 把用過的數據扔掉,重新與環境繼續互動生成數據 (因為 policy 更新了,舊的數據沒有參考價值)
- 繼續用新的數據 update agent policy
- ...
顯而易見,on-policy 的方式是存在一定問題的,比如進行飛機大戰的游戲,輸入 DNN 的 state 是用 image 表示的,訓練 -> sample -> 訓練 這樣的方式非常耗時,并且一旦原有的 policy 更新了以后,
上述梯度中分布 就變了,之前在老的
上面采樣的數據就沒用了,這意味著每次更新 policy 會浪費大量的數據,并且需要大量的時間進行 sampling。
所以針對這種 on-policy 研究人員希望能夠在不影響 agent 與環境互動的前提下持續地對我們需要的 agent 進行更新,于是便有了 off-policy,這里主要講 PPO/TRPO 和 PPO2 這幾種方法。
Important Sampling
Important Sampling,它并不是 RL 里面獨有的方法,簡要來說就為了實現線下學習我們需要用一個不同的分布 去估計我們所需要的分布
。在 off-policy 中體現為:我們想用另外一個
去跟環境做互動,使用
收集到的數據去訓練我們想要的
,這個流程就像你讓一個小朋友去看另外一個小朋友玩游戲,并從中學到游戲的方法。
通過這種方法 與環境互動獲取到的數據可以被使用多次,并且不需要考慮
變化時數據就會失效的問題。
具體來說,important sampling 中用一個分布 來估計另一個分布
可以這樣表示:
Proximal Policy Optimization (PPO)
將這種 important sampling 的方式應用到 policy gradient 上面,我們可以得到:
假設 ,那么上面的式子可以寫成:
用 去估計
的分布,實際上就是用 agent
去和環境互動,根據其互動的數據去更新我們的 policy。這里 important sampling 其實有一個問題,雖然兩個分布的 mean 是一樣的,但是他們的方差是不同的,在 sample 數量不夠多的話,
的方差就會變得很大,所以采樣的時候我們應該盡可能的保持多的樣本數據來保證準確率,同時要保證兩個分布不能差別太大。
借助之前的公式 ,我們可以用 gradient 去反推原來的 objective function,得到函數
:
非常的直觀:我們用
去做 demonstration 從而優化我們想要的參數
,但是由于這個 objective function
牽扯到 important sampling,為了保證 important sampling 的效果,我們要讓兩個分布盡可能的相似,所以 PPO 就應運而生了: 在做訓練的時候多加一個 constrain:
(
為常數),這一項代表著兩個分布
之間的 KL 距離,減去這一項我們可以得到:
其中如果 越大 (即
和
越不相似),最終的
就會越小。通過優化這個式子求其最大值,我們可以達到更好的強化學習效果。
要注意的是,這里的 并不是參數上的距離,而是這些 action 之間的相似度。總的來說,PPO 的算法可以描述為:
- 初始化一個 policy
- 在每次迭代過程中:
- 使用
去與環境交互,收集數據
并且計算
- 找到
去優化
, 其中
- 使用
那么對于 PPO 約束條件 中的
要怎么設定呢?實際上可以很直觀地設定一個最大值和最小值,如果兩個分布的 KL 距離已經到了最大值,然后整個式子還是沒有起到明顯的約束作用,就增大
。同理,如果距離小到了最小值,整個式子的值仍然偏大,這時候就需要動態減小
的值:
- 如果
, 增加
- 如果
, 減小
Trust Region Policy Optimization (TRPO)
另外一種方法叫做 TRPO: Trust Region Policy Optimization, 它和 PPO 唯一不一樣的地方是這個 constrain 設計的方式有點不一樣,它將約束條件放到了式子外面:
但是實際上實現 TRPO 的時候,式子外面的約束條件是非常難處理的,一般不推薦 (因為 PPO 和 TRPO 效果差不多,但是實現起來簡單很多)。
PPO2
PPO2 算法是在 PPO 算法上衍生的另外一種算法,本質也是為了使得兩個分布 的差距不要太大,數學表示為:
的意思是說:
這樣就可以動態地將 的值限定在
到
之間,達到兩個分布不會相差太多的效果。而取最小值是因為,當
時,我們希望 objective function 越大越好,但是一旦大過了
,這個式子就不再有 benefit 了,因為不滿足兩個分布差別不要太大的這個約束條件,同理當
的時候也是一樣。
Q-Learning
除了直接學習一個 policy,我們還可以從另外一個角度出發,去學習一個 critic,這也被稱作是 value-based 的學習方法。Critic 就是一個評價者,去客觀地評價你這個 action 做得好還是不好。
這里需要引入一個 state value function ,代表著在 state s 之后所有 reward 累加的期望值。
越大,意味著給定 state
開始到游戲結束,這個 agent
可能獲得的 reward 就越多(前景越光明),在某種意義上來說,這就是一個 critic,但是目前的
只是一個 scalar function,不能夠給出指導性的意見。
Monte-Carlo (MC) 和 Temporal-difference (TD)
那怎么去估計這樣一個 呢?這里一般用兩種方法,MC 和 TD,其中各有優劣。
MC 的方法很簡單,一般來說 MC 會訓練一個 DNN,給定一個 state 輸入,這個網絡返回預測的從
往后所有 reward 的總和
,我們希望它與實際的總和
越接近越好。
簡要表示就是這個樣子:
另外一種方法是 TD,和 MC 有所不同的是,TD-based 的方法不用計算積累的所有 reward 和,意味著你必須走完整個流程直到結束才能夠完成 MC-based 的估測,有的游戲非常耗時,使用 MC-based 的方法可能在短時間是無法獲得多少數據的。
TD-based 的方法具體來說是針對每個 step,我們可以得到 ,那么從這個式子可以看出,對應的
實際上是滿足:
具體的實現我們可以構造兩個一樣的網絡 ,分別接收
和
,之后我們將輸出作差
,盡量使得差值和給定的訓練數據
保持一致。
這樣我們就不需要整場游戲的所有 reward 和進行訓練,能夠通過差分的方式,利用前后步之間的 reward 差估測出 ,這就是 TD 的方法。
MC 和 TD 各有優劣,MC 最大的問題就是,因為 是有隨機性的,這種隨機性來自環境本身和 agent 之后所做的動作的不同,一旦累加以后
會產生很大的方差,而這個問題在 TD 中并不明顯,在 TD 中具有隨機性的是前后兩步之間的 reward r,而并不是 r 的累加。
但是在 TD 中也存在一個問題, 中
也是一個估計值,這個值有可能是不準確的,這個不準確會直接造成最終
的不準確。
State-action Value Function
比起 ,我們引入一個進階的版本,也就是我們接下來在 Q Learning 中重點要研究的 Q 函數。與之前的
不同的是,
給定了計算初始的 state ,但是沒有指定初始的 action,初始的 action 完全是由 policy 自己決定的。Q 函數的不同之處在于其不僅給定一個初始狀態,更指定在遇見這個狀態之后應該做出怎么樣的 action:
剩下就是計算 cumulated reward,這個和 V 函數是一樣的。那么如何使用 Q 函數進行強化學習呢?
Q-Learning 的算法可以簡單地用三步來表示:
- 初始化一個 actor
- 在一次迭代過程中:
- actor
與環境做互動,并且收集數據
- 用上述的數據,TD 或者是 MC 的方法估測出 Q 函數
- 根據 Q 函數,找到一個永遠比
“更好的”
- 用
去替換原有的
- actor
這里的 “更好” 指的是對任意的 s: ,
, 即對所有可能的 action a 來說,能夠代入
并且獲得最大值的那個 action 就是
會采取的 action。這里有個小問題,如果 action 是離散的,那么只要一個一個代進去算就可以得到
,但是如果 action 是連續的就不容易計算。
證明如果存在 ,那么對任意的 s 有
:
即針對某一個特定的 s , 所采用的 action 一定不比
采取的有更小的 reward,那么加入每一步都 follow
給的 action:
Target Network
如果使用 TD-based 的方式訓練神經網絡來估計 Q 函數的時候,需要初始化兩個一樣的 DNN:
兩個網絡輸出的差就是 ,但是在訓練的過程中輸入
是負責產生 target 的,如果保持兩個網絡一直一樣,相當于在訓練的過程中目標網絡是會變化的,這是不好的,所以在訓練的時候會現將目標網絡固定住,直到某個固定的跌代次數之后再更新。
Exploitation 和 Exploration
在強化學習中,一直存在著一個 trade-off:就是探索新的 action 還是專注獲得最大的 reward。這里不得不提到一個非常經典的問題:multi-arm bandit,多臂老虎機問題。
具體來說就是 你進了一家賭場,前面有著 K 臺老虎機,每臺老虎機去搖動的時候都有一定概率吐出一定量的錢,也有可能不吐錢,這個你沒法事先知道,現在你有 T 個錢幣,一個錢幣只能搖動一臺老虎機一次,怎樣做你才能夠擁有最大的金錢回報?
這實際上牽扯到一個權衡,你想知道哪臺老虎機吐錢的概率最大,這需要你去嘗試:Exploration。當然,探索是有成本的,因為你可能花了很多錢搖了各種各樣的老虎機,但是收獲的回報微乎其微。你還想獲得最大的收益,如果你發現了一個相對吐錢概率高的老虎機,你得多搖搖才行,這是 Exploitation。
那么在 Q-Learning 中如果一開始在 state 有三個可能的 action
,一開始由于這三種 action 都沒有被 sample 到,所以他們的 reward 是不存在的,這時候如果其中某個 action 被 sample 到了并且取得了好的反饋,根據 Q 函數永遠都會選擇最大 reward 的 action 去執行,那么這個 action 就會一直被 sample,而另外兩個得不到被 sample 的機會,這顯然是不合理的。
那么該怎么解決這個問題呢?
一種非常直觀地方法叫 Epsilon Greddy,具體表示為:
在一定概率下隨機亂試,起到 exploration 的作用。這個 一般會隨著時間往后推移而減小,因為越往后可能沒有嘗試過的新 action 就越少,沒必要使用這么大的概率去進行探索。
或者覺得隨機亂試不是一個好方法,那么可以參考 policy gradient 的方法,給 Q 函數構建一個概率分布,假設某個 action 的 Q value 越大,那么采取這個 action 的幾率也就會越大,但是不代表其他 action 不會被 sample 到。這個具體的方法叫做 Boltzmann Exploration:
之所以要用 Exp,是因為 Q value 可能是有正有負的,之后再做歸一化。
Reply Buffer
在 Q Learning 中,我們有一個 policy 去和環境做互動并且產生數據,reply buffer 指的是我們會把所有的數據放到一個類似于緩沖區的地方,具體的數據含有 ,這個 buffer(緩沖區) 里面可能包含非常非常多的數據,隨著互動的 policy 不斷更新,buffer 里面自然也會包含不同的 policy 收集到的數據,并且這個 buffer 只有在轉滿的時候才會把舊的數據丟掉。
實際上當我們有了這個 reply buffer 以后,整個學習過程可以看作是 off-policy 的,其好處就是,DRL 往往會花很多時間與環境做互動,所以使用了 reply bufer 可以增加訓練效率。
并且 reply buffer 里面含有不同的 policy 數據,可以在訓練深度神經網絡的時候起到增加數據多樣性的目的,因為數據并不是一筆筆完整的 episode 而是每一步產生的結果,所以不同的 policy 也可以用來估測 。
綜合上述算法和 tips,一個典型的 Deep Q-Learning 的算法可以描述為:
- 先初始化兩個 Q function: Q 和 target Q function
- 在每個 episode 中:
- 在每次迭代中:
- 給定一個輸入 state
,根據 Q 采取相應的 action
- 得到 reward
,并且進入下一個 state
- 把上面收集到的
放到 reply buffer 中
- 從 reply buffer 中 sample 數據,一般按照 batch 來 sample
- 訓練,更新 Q 的參數使得
接近于
- 給定一個輸入 state
- 每 N 次迭代完成之后更新
- 在每次迭代中: