一個強(qiáng)化學(xué)習(xí)的入門者,僅用于自己學(xué)習(xí)的記錄
強(qiáng)化學(xué)習(xí)
Q-learining 算法
Pytorch 強(qiáng)化學(xué)習(xí)算法實現(xiàn)
https://github.com/p-christ/Deep-Reinforcement-Learning-Algorithms-with-PyTorch
# 講的很詳細(xì), 循序漸進(jìn),含有代碼,很適合入門
DQN算法
一些概念
當(dāng)前累計獎勵增量更新:
-
占用度量: 歸一化的占用度量用于衡量在一個智能體決策與一個動態(tài)環(huán)境的交互過程中,采樣到一個具體的狀態(tài)動作對(state-action pair)的概率分布
給定兩個策略及其與一個動態(tài)環(huán)境交互得到的兩個占用度量,那么當(dāng)且僅當(dāng)這個兩個占用度量相同時,這兩個策略相同。
策略: 指的是智能體在不同的狀態(tài)下如何選擇動作。 強(qiáng)化學(xué)習(xí)的策略在訓(xùn)練過程中不斷的更新, 一個策略對應(yīng)的價值就是一個占用度量下對應(yīng)的獎勵的期望。 因此尋找平最優(yōu)策略就是尋找最優(yōu)占用度量。
強(qiáng)化學(xué)習(xí)最終的目標(biāo)就是尋找最優(yōu)策略,使智能體和環(huán)境交互中的價值最大化。
馬爾可夫過程
- 狀態(tài)之間的轉(zhuǎn)移, 用元祖
表示,其中
表示狀態(tài)的集合,
表示狀態(tài)轉(zhuǎn)移的概率矩陣
- 給定一個馬爾可夫的過程, 我們可以從某個狀態(tài)出發(fā),根據(jù)它的狀態(tài)轉(zhuǎn)移矩陣生成一個狀態(tài)序列(episode),這個步驟叫做采樣(sampling)
馬爾可夫獎勵
- 在馬爾可夫過程中加入獎勵因子
和折扣因子
, 就得到馬爾可夫獎勵過程(MRP)。
- 在一個馬爾可夫獎勵過程中,從
時刻的狀態(tài)
開始直到終止?fàn)顟B(tài)時,所有獎勵的衰減之和稱為回報。
其中表示
時刻獲取的獎勵。
這里我的理解是,因為從某個狀態(tài)
開始, 按照概率轉(zhuǎn)移矩陣就可以獲取下一個狀態(tài),假設(shè)可以走到終止?fàn)顟B(tài)。這時候形成的序列中,有些狀態(tài)會出現(xiàn)多次,有些出現(xiàn)一次,有些甚至不出現(xiàn)。假設(shè)采樣了一個的狀態(tài)序列為
, 那么在第
時刻(本質(zhì)上就是采樣的順序)
的期望回報
就是按照上面的公式計算整個序列,序列中也可能會包含同樣的狀態(tài), 比如第
時刻的
。
價值函數(shù)
在馬爾科夫獎勵中,一個狀態(tài)的期望回報(即從這個狀態(tài)出發(fā)的未來累積獎勵的期望),稱為這個狀態(tài)的價值。 所有狀態(tài)的價值就組成了價值函數(shù),價值函數(shù)的輸入為某個狀態(tài),輸出為這個狀態(tài)的價值:
利用狀態(tài)轉(zhuǎn)移矩陣,可得到貝爾曼方程計算狀態(tài)價值函數(shù):
是
狀態(tài)獲取的即時獎勵。
將上式子寫成矩陣的方式:
馬爾可夫決策
在馬爾科夫獎勵過程中加上動作,就稱為馬爾可夫決策過程。
智能體的策略用
表示,策略函數(shù)
表示輸入狀態(tài)為
時,采用動作
的概率。
基于策略
的狀態(tài)價值函數(shù)為:
動作價值函數(shù)表示馬爾可夫決策過程遵循決策
時, 對當(dāng)前狀態(tài)
執(zhí)行動作
得到的期望回報:
狀態(tài)價值函數(shù)和動作價值函數(shù)的關(guān)系:
綜上得到狀態(tài)價值函數(shù)和動作價值函數(shù)的貝爾曼期望方程:
- 馬爾可夫決策中狀態(tài)的獎勵,通過動作邊緣化:
- 馬爾可夫決策中狀態(tài)的轉(zhuǎn)移概率,通過動作邊緣化:
- 這是馬爾卡夫決策過程就轉(zhuǎn)換為馬爾可夫獎勵
蒙特卡洛方法(要先完成序列采樣)
- 使用蒙特卡洛方法來估計一個策略在一個馬爾可夫獎勵過程中的狀態(tài)價值函數(shù):
- 根據(jù)上述公式,當(dāng)計算一個狀態(tài)的期望回報時,可以使用策略在MDP上采樣很多條序列,計算從這個狀態(tài)出發(fā)的回報再求期望。
- 簡單的說,就是不斷的進(jìn)行序列采樣,計算采樣到狀態(tài)的累計獎勵。
- 使用策略
采樣若干條序列:
- 對每一條序列中的每一時間步
的狀態(tài)
進(jìn)行以下操作:
- 更新狀態(tài)
的計數(shù)器
;
- 更新狀態(tài)
的總回報
;
- 每一個狀態(tài)的價值被估計為回報的平均值
。
-
狀態(tài)
在序列中出現(xiàn)一次,就計算一次期望回報,當(dāng)采樣很多次序列時,假設(shè)狀態(tài)
出現(xiàn)了
次,求均值就行。
根據(jù)大數(shù)定律,當(dāng),有
。計算回報的期望時,除了可以把所有的回報加起來除以次數(shù),還有一種增量更新的方法。對于每個狀態(tài)
和對應(yīng)回報
,進(jìn)行如下計算:
核心代碼 (在這里是按照逆序列更新的)
def MC(episodes, V, N, gamma):
# episodes 采樣的序列列表【[s0---> s2--->s4--->....s_結(jié)束], [s0---> s3--->s8--->....s_結(jié)束],...】
for episode in episodes:
# episode 一個序列[s0---> s2--->s4--->....s_結(jié)束]
G = 0
for i in range(len(episode) - 1, -1, -1): #一個序列從后往前計算
(s, a, r, s_next) = episode[i]
# 即使獎勵+折扣回報
G = r + gamma * G
# 計數(shù)器
N[s] = N[s] + 1
# 更新狀態(tài)s的價值
V[s] = V[s] + (G - V[s]) / N[s]
- 不同策略訪問到的狀態(tài)的概率分布是不同的,因此策略的狀態(tài)價值函數(shù)是不同的。
動態(tài)規(guī)劃(必須知道轉(zhuǎn)移概率矩陣)
策略迭代
- 策略評估: 使用貝爾曼期望方程來得到一個策略的狀態(tài)價值函數(shù), 當(dāng)我們知道獎勵函數(shù)和狀態(tài)轉(zhuǎn)移函數(shù),根據(jù)下一個狀態(tài)的價值來計算當(dāng)前狀態(tài)。根據(jù)動態(tài)規(guī)劃的思想,把計算下一個可能狀態(tài)的價值當(dāng)做一個子問題, 把計算當(dāng)前狀態(tài)的價值看作當(dāng)前問題。 在得知子問題的解后,就可以求解當(dāng)前問題。更一般的,考慮所有的狀態(tài),就變成了用上一輪的狀態(tài)價值函數(shù)來計算當(dāng)前這一輪的狀態(tài)價值函數(shù),即
當(dāng),
. 由于不斷需要做貝爾曼期望方程的迭代,策略評估需要很大的計算代價,實際中,某輪
的值非常小,則可以結(jié)束。
- 這里完全沒看懂。。。很模糊。貝爾曼方程是根據(jù)下一個狀態(tài)計算當(dāng)前狀態(tài),怎么就成了使用上一輪狀態(tài)計算當(dāng)前這一輪的了?
代表的是每一輪。
- 雖然看懂代碼的過程了,但是還不明白為啥這么算? 代碼的過程是,每輪遍歷所有的狀態(tài)和動作,然后利用上一輪計算的狀態(tài)價值,使用貝爾曼來更新當(dāng)前這一輪的狀態(tài)價值,然后執(zhí)行很多輪。。。也就是不斷使用貝爾曼方程計算狀態(tài)價值,一直到收斂。
- 突然又想明白了,在計算當(dāng)前狀態(tài)時,無法知道下一個狀態(tài)的值,因此,就是用上一輪獲取的下一個狀態(tài)的值來計算。 另一個問題是,為何要一輪一輪的計算? 每一輪代表的是什么?
策略提升: 假設(shè)智能體在某一個狀態(tài)
采取動作
之后的動作依舊遵循策略
, 此時得到的期望回報就是動作價值
, 如果有
, 說明在該狀態(tài)下存在一個更好的策略回報更高。現(xiàn)在假設(shè)存在一個策略
, 在任意一個狀態(tài)
下,都滿足
, 則任意狀態(tài)下有:
我們可以直接貪心地在每一個狀態(tài)選擇動作價值最大的動作,也就是在狀態(tài)
中,選擇動作價值最大的那些
:
策略迭代和價值迭代通常只用于有限的馬爾科夫決策,即狀態(tài)空間和動作空間是離散的。
策略迭代是 策略評估和策略提升不斷循環(huán)交替,直至最后得帶最優(yōu)策略的過程。 對當(dāng)前測策略進(jìn)行策略評估,得到其狀態(tài)價值函數(shù),然后根據(jù)該狀態(tài)價值函數(shù)進(jìn)行策略提升得到一個更好的新策略,持續(xù)進(jìn)行。。。直到收斂。
價值迭代 : 使用貝爾曼最優(yōu)方程進(jìn)行動態(tài)規(guī)劃,得到最終的最優(yōu)狀態(tài)價值
- 如果只在策略評估中進(jìn)行一輪價值更新,然后直接根據(jù)更新后的價值進(jìn)行策略提升,這樣是否可以呢?答案是肯定的
為啥是肯定的?
- 價值迭代的更新方式, 就是始終選擇最大的動作價值:
- 在策略迭代中:策略評估---策略提升---策略評估---策略提升---策略評估---策略提升---策略評估。。。。一直進(jìn)行下午,直到收斂, 這時就可以獲取策略了, 其中策略評估需要很多輪
- 在價值迭代在中: 價值評估----獲取策略, 就結(jié)束了, 其中價值評估也是很多輪(明顯少于策略評估的輪數(shù))。
- 我的理解是,價值評估中, 每次選擇的都是最優(yōu)價值進(jìn)行評估,加快了收斂速度
時序差分
- 無模型的強(qiáng)化學(xué)習(xí)(model-free reinforcement learning):馬爾可夫決策過程的狀態(tài)轉(zhuǎn)移矩矩陣無法直接獲取,也不知道獎勵函數(shù),智能體只能和環(huán)境交互采樣數(shù)據(jù)進(jìn)行學(xué)習(xí)。
- 在線策略學(xué)習(xí): 使用在當(dāng)前策略采樣得到的樣本進(jìn)行學(xué)習(xí), 一旦策略更新,樣本被拋棄
- 離線策略學(xué)習(xí): 使用經(jīng)驗回放池將之前采樣得到的樣本手機(jī)起來再次利用
- 蒙塔卡洛的價值增量更新為:
。 需要采樣很多序列,序列中每個狀態(tài)可能出現(xiàn)很多次,按照順序記為
時刻,
表示第
時刻的狀態(tài)。蒙特卡洛需要采樣整個序列結(jié)束后計算回報。
- 時序差分,用當(dāng)前獲取的獎勵加上下一個狀態(tài)的獎勵的價值估計來作為當(dāng)前狀態(tài)的回報:
,
其中被稱為時序差分,
是更新步長。本質(zhì)上,
。
Sarsas算法, 在線策略
- 在不知道獎勵函數(shù)和狀態(tài)轉(zhuǎn)移函數(shù)的情況下,如何進(jìn)行策略提升?使用時序差分來估計動作價值函數(shù)
-
Sarsa 的具體算法如下:
Saras - 核心代碼
class Sarsa:
""" Sarsa算法 """
def __init__(self, ncol, nrow, epsilon, alpha, gamma, n_action=4):
self.Q_table = np.zeros([nrow * ncol, n_action]) # 初始化Q(s,a)表格
self.n_action = n_action # 動作個數(shù)
self.alpha = alpha # 學(xué)習(xí)率
self.gamma = gamma # 折扣因子
self.epsilon = epsilon # epsilon-貪婪策略中的參數(shù)
def take_action(self, state): # 選取下一步的操作,具體實現(xiàn)為epsilon-貪婪
if np.random.random() < self.epsilon:
action = np.random.randint(self.n_action)
else:
action = np.argmax(self.Q_table[state])
return action
def update(self, s0, a0, r, s1, a1):
td_error = r + self.gamma * self.Q_table[s1, a1] - self.Q_table[s0, a0]
self.Q_table[s0, a0] += self.alpha * td_error
- 訓(xùn)練核心
# 根據(jù)state先拿到action
action = agent.take_action(state)
done = False
while not done:
# 根據(jù)當(dāng)前的action,拿到下一個狀態(tài)和即時獎勵
next_state, reward, done = env.step(action)
# 采樣下一個action
next_action = agent.take_action(next_state)
episode_return += reward # 這里回報的計算不進(jìn)行折扣因子衰減
agent.update(state, action, reward, next_state, next_action, done)
state = next_state
action = next_action
Q-learning 算法 ,離線策略
- Q-learning的價值更新:
-
具體流程;
Q-learning - 核心代碼
class QLearning:
""" Q-learning算法 """
def __init__(self, ncol, nrow, epsilon, alpha, gamma, n_action=4):
self.Q_table = np.zeros([nrow * ncol, n_action]) # 初始化Q(s,a)表格
self.n_action = n_action # 動作個數(shù)
self.alpha = alpha # 學(xué)習(xí)率
self.gamma = gamma # 折扣因子
self.epsilon = epsilon # epsilon-貪婪策略中的參數(shù)
def take_action(self, state): #選取下一步的操作
if np.random.random() < self.epsilon:
action = np.random.randint(self.n_action)
else:
action = np.argmax(self.Q_table[state])
return action
def update(self, s0, a0, r, s1):
td_error = r + self.gamma * self.Q_table[s1].max() - self.Q_table[s0, a0]
self.Q_table[s0, a0] += self.alpha * td_error
- 訓(xùn)練核心
while not done:
# 直接根據(jù)state獲取action
action = agent.take_action(state)
# 根據(jù)action 獲取下一個狀態(tài)和即時獎勵
next_state, reward, done = env.step(action)
episode_return += reward # 這里回報的計算不進(jìn)行折扣因子衰減
agent.update(state, action, reward, next_state)
state = next_state
離線和在線策略的差異
- 我們稱采樣數(shù)據(jù)的策略為行為策略, 用這些數(shù)據(jù)來更新的策略為目標(biāo)策略
- 在線策略(on-policy)算法表示行為策略和目標(biāo)策略是同一個策略
- 離線策略(off-policy)算法表示行為策略和目標(biāo)策略不是同一個策略
- Sarsa 是典型的在線策略算法,而 Q-learning 是典型的離線策略算法。判斷二者類別的一個重要手段是看計算時序差分的價值目標(biāo)的數(shù)據(jù)是否來自當(dāng)前的策略
- 對于Sarsa , 更新涉及的五元組
來自當(dāng)前策略的采樣
- 對于Q-learning , 更新用到的四元組
, 其中
和
是給定的,
和
不一定來自于當(dāng)前策略。
Sarsa 和 Q-learning 的對比
DQN算法(使用神經(jīng)網(wǎng)絡(luò)實現(xiàn)Q-learning算法)
- 寫的很好
- Q-learning 需要維護(hù)狀態(tài)-動作表,因此只適用有限狀態(tài)-動作。
- 因此,使用神經(jīng)網(wǎng)絡(luò)來學(xué)習(xí)一個擬合函數(shù),輸入為狀態(tài)
, 輸出每一個動作的
值,也就是輸出一個向量
, 其中每個值代表了狀態(tài)
下執(zhí)行動作
的
值。
現(xiàn)在最大的問題是,如何訓(xùn)練Q網(wǎng)絡(luò)? 神經(jīng)網(wǎng)絡(luò)需要損失函數(shù)來提供信號進(jìn)行參數(shù)更新,如何設(shè)置損失?也就是如何為Q網(wǎng)絡(luò)提供 有標(biāo)簽的樣本訓(xùn)練網(wǎng)絡(luò)?
- 由于Q-learning的更新過程為:
它的目標(biāo)就是使不斷逼近
因此,損失函數(shù)定義為(為神經(jīng)網(wǎng)絡(luò)的參數(shù)):
經(jīng)驗回放
- 維護(hù)經(jīng)驗回放池, 將每個采樣的的四元組數(shù)據(jù)(狀態(tài)、動作、獎勵、下一狀態(tài))存儲到回放緩沖區(qū)中,訓(xùn)練 Q 網(wǎng)絡(luò)的時候再從回放緩沖區(qū)中隨機(jī)采樣若干數(shù)據(jù)來進(jìn)行訓(xùn)練。
- 使樣本滿足獨立假設(shè)。
- 提高樣本效率。
目標(biāo)網(wǎng)絡(luò)
- 更新目標(biāo)時,
不斷的逼近
,由于時序差分的誤差目標(biāo)本身就包含神經(jīng)網(wǎng)絡(luò)的輸出,因此,網(wǎng)絡(luò)參數(shù)的變化導(dǎo)致目標(biāo)也不短變化。 因此DQN使用了目標(biāo)網(wǎng)絡(luò): 在訓(xùn)練中暫時將時序差分目標(biāo)中的Q網(wǎng)絡(luò)固定。因此,DQN使用兩套Q網(wǎng)絡(luò):
(1) 訓(xùn)練網(wǎng)絡(luò)計算
(2)目標(biāo)網(wǎng)絡(luò)計算
訓(xùn)練網(wǎng)絡(luò)正常更新,每隔個step就將訓(xùn)練網(wǎng)絡(luò)的參數(shù)同步到目標(biāo)網(wǎng)絡(luò)。
DDQN(Double DQN)
- 出現(xiàn)的原因: Q-learning會對
高估。
Dueling DQN
- 當(dāng)
比較大時, 是因為
比較好還是
比較好? 所以定義一個優(yōu)勢函數(shù)
可以理解為: 對于中某一步行動的改變(做出了動作
), 所帶來的變化。簡單理解,就是在一個狀態(tài)
上進(jìn)行了一個
所帶來的變化。
- 由于
我們不難推出:
狀態(tài)價值來自于所有動作的動作價值函數(shù)的期望。
策略梯度算法
又看不懂了。。。。


