Reinforcement Learning Chapter2

llllllgllllll發表於2024-02-05

本文參考《Reinforcement Learning:An Introduction(2nd Edition)》Sutton

K臂賭博機

問題描述:你有k個選擇,每個選擇對應一個獎勵,收益由所選動作決定的平穩機率分佈產生,目標為最大化某段時間內的總收益期望。

聯絡我們在chapter1中提到的reward,value, action等概念,我們在這個K臂賭博機上可以這樣思考:

在時刻t, 我們基於現有策略,選擇了action(a),帶來了即時獎勵(reward)R(s,a),根據R(s,a)我們自然的修正了對於動作a的value估計與對於狀態s的value估計,從而更新了我們的策略。

對於K臂賭博機,我們不需要考慮狀態價值,因為每一次的選擇與下一次的收益無關(非Markov過程),所以我們應當著重考慮如何根據我們的reward來進行對於a的value估計,同時策略q在這個問題中並不重要,一個顯然的事實就是,最優策略是若確定了所有a的value,我們每次都將選擇價值最高的a,這個一定能達到目標。然而我們並不能確定,所以需要靠估計。

此時出現了一個困境:如果持續對動作的價值進行估計,則對任意時刻t總有至少一個動作的value估計是最高的,這時不妨稱這種動作為貪心動作,那麼如果我們直接在不確定所有a的value的情況下直接套用最優策略,每次都選擇當前最優a,那麼很可能發生的情況是,若此時有一個a的動作收益是確定的,另幾個a‘的收益與a相差不多但是有很大的不確定性(收益由所選動作決定的平穩機率分佈產生),這種不確定性足夠使得至少有一個動作實際上會好於貪心動作,但是如果你一直選擇貪心動作你將無法發現這個更優的動作。所以該如何平衡“探索”還是“貪心”?這個問題是RL中的一個經典問題。

接下來我們從對動作的價值估計演算法談起:

一種自然的方法是計算實際收益的平均值來估計動作價值:在k-armed bandit問題上使用他是有其適用性的,我們的每次選擇不隨時間狀態改變其收益的機率分佈,所以根據大數定律,在足夠次的取樣之後,實際收益的平均值將收斂於實際動作價值。

 Qt(a) -> q*(a)當取樣次數足夠大;

那麼現在我們在上述方法的基礎上考慮如何選擇動作:在上文已經說明我們陷入了“探索”與“貪心”的困境,針對於這個困境,一種比較顯然的方法是我們在大部分時間表現的比較貪心,偶爾隨機探索,這種方法被稱為ε-greedy方法。具體而言是這樣的,在每一步我們以1-ε機率選擇貪心策略,以ε機率獨立於動作價值估計等機率地隨機選擇所有動作之一。這個方法在時刻足夠長的時候將把每一動作無限取樣,得到對所有動作的準確價值估計,從而使得選擇最優動作的機率收斂到1-ε。

import random
import matplotlib.pyplot as plt

k = 10
base_reward = [round(random.uniform(0,1),3) for i in range(k)] # k=10 10-armed Bandit 
print(base_reward)

reward_expectancy=[0 for i in range(k)]
print(reward_expectancy)

steps = 1000
current_cumulative_value = [[0,0] for i in range(k)]
for i in range(steps):
    epsilon_reward = random.uniform(-0.2,0.2)
    choice = random.randint(0, 9)
    current_cumulative_value[choice][0] += base_reward[choice] + epsilon_reward
    current_cumulative_value[choice][1] += 1
    
for i in range(k):
    print(f"{i} value is {current_cumulative_value[i][0]/current_cumulative_value[i][1]} and {base_reward[i]}")

print("********************************")

#action_value_method
greedy_epsilon = 0.1
steps = 10000
current_cumulative_value = [[0,0] for i in range(k)]
correct_rate = []
correct_choice_num = 0
for i in range(steps):
    epsilon_reward = random.uniform(-0.2,0.2)
    if (random.uniform(0,1) > greedy_epsilon):
        choice = reward_expectancy.index(max(reward_expectancy))
        current_cumulative_value[choice][0] += base_reward[choice] + epsilon_reward
        current_cumulative_value[choice][1] += 1
        reward_expectancy[choice] = current_cumulative_value[choice][0]/current_cumulative_value[choice][1]
    else:
        choice = random.randint(0, 9)
        current_cumulative_value[choice][0] += base_reward[choice] + epsilon_reward
        current_cumulative_value[choice][1] += 1
        reward_expectancy[choice] = current_cumulative_value[choice][0]/current_cumulative_value[choice][1]
    if choice == base_reward.index(max(base_reward)):
        correct_choice_num += 1
    correct_rate.append(correct_choice_num/(i+1))
        
for i in range(k):
    print(f"{i} value is {reward_expectancy[i]} and {base_reward[i]}")
plt.plot(correct_rate)

上述為10-armed bandit的一個模擬,讀者可以嘗試修改其中的引數如steps、epsilon甚至是對動作價值初始化的方式來更好感受RL。

上述程式碼在更新動作價值估計的部分仍有可以最佳化的地方,這裡可以考慮使用一種叫做增量式更新的方法(這種方法很重要,在後面的許多章節會持續提到):

 在這個問題中對第n次更新:stepsize = 1/n,target=Rn,oldEstimate=Qn
對於一個收益分佈不隨時間機率變化的bandit問題,下述演算法是一種解決方法

然而,事實上很多RL問題的收益分佈是動態的,上述的方法並不適用,此時又該如何?

這裡需要引入EMA的概念,指數移動平均:讀者不妨參考這篇blog:【煉丹技巧】指數移動平均(EMA)的原理及PyTorch實現 - 知乎 (zhihu.com),簡而言之EMA相比於之前的直接平均的好處在於它更關注近期資料,為他們賦予了更高的平均權重,從而減輕了資料噪聲的影響。所以我們可以得到新的Qn的恆定步長更新公式:

 

這裡值得一提的是,從數學上看若要Qn以機率1收斂於真實值時,需要有:

但顯然EMA不滿足上述式子,所以所得的Q的估計也會隨最近的收益而變化,不過這不恰好對應了動態收益分佈的特徵嗎?

讀者不難發現我們對Q的更新演算法或多或少都依賴於其初始化的值,對取樣平均法而言這種初始化的偏差會在每個動作都被嘗試後消失, 對恆定步長的方法而言則是會隨時間逐漸減小。

那麼如何讓恆定步長也能避免偏差?我們嘗試為恆定步長引入修正係數,並且這個修正係數應當不依賴於初始值:

聯絡Q的更新式即可發現此時Qn與Q1無關。


 

誠然ε-greedy是一種有效的方法去平衡試探-貪心;但是對ε-greedy而言,任何狀態的action只分兩類:最優和普通,它將所有非當前最優action等同對待,試探時隨機從中抽取動作,這顯然是一種盲目的選擇。一種比較自然的做法是在探索時選擇那些更有潛力成為最優的動作(簡單而言就是當前方差比較大但是當前對該action的估計與最優足夠接近),所以基於UCB(置信度上界)的方法被提出了,公式如下:

Nt(a):動作a在t時刻前被選擇的次數;c:試探程度,當c=0時,UCB退化為greedy(不是ε-greedy!),當Nt(a)=0時自動認為a是滿足最大化條件的動作(即直接選擇採用動作a),這樣基本可以保證任何可能動作在學習過程中都被選取過。而且隨著t不斷增大,若動作a價值估計低(Qt(a)太小)或者被選擇太多次(Nt(a)太大),則動作a被選擇的機率將下降。

UCB是一種很有效的演算法,但也有其侷限之處:1、上述式子一般由於平穩獎勵分佈,非平穩情況UCB方法的複雜度較高;2、對於較大的狀態空間,UCB目前沒有很好的近似手段;

以上兩種方法都是基於動作價值的估計來選擇動作,但這並不是唯一的方向;動作之間的關係不僅可以用動作價值這樣的具體數值來表示,也可以相互比較來進行衡量;

這裡我們基於隨機梯度上升思想提出了一種演算法:

首先定義偏好函式:

邏輯很簡單,就是拿當前的收益和之前選擇該動作的收益的估計(這裡是均值的形式)做比較,如果當前收益大就增大偏好函式值使得下一次選擇更有可能選到這個動作,其他動作則是相應減少,但保持總機率之和不變;理論推導讀者自行閱讀教材(可參考:梯度賭博機演算法:公式推導 - 知乎 (zhihu.com)

注意一點,這裡對於該動作的收益估計有很多種方式可以做到,取均值只是為了方便實踐並且簡單,但它對演算法的最終效果無太大影響,只是影響收斂的速度。

還有一種演算法叫關聯搜尋,就是為動作與狀態構建一個動作-狀態對,進而學習任務相關的動作策略,之後我們將進一步討論它。

 

相關文章