強化學習基礎篇(二十一)網格問題

強化學習基礎篇(二十一)網格問題

該問題基于《Reinforcement Learning: An Introduction》在第三章中給出了一個簡單的例子:Gridworld, 以幫助我們理解有限MDPs串慰。

1佳鳖、網格問題描述

如下圖所示的長方形網格代表的是一個簡單的有限MDP锭魔。網格中的格子代表的是環(huán)境中的狀態(tài)您宪。在每個格子中,有四個可選的動作:東、南、西和北,每個動作都會使智能體在對應的方向上前進一格糊饱。如果采取的動作使得其不在網格內,則智能體會在原位置不移動颠黎,并且得到一個值為-1的收益另锋。除了將智能體從特定的狀態(tài)A和B中移走的動作外,其他動作的收益都是0狭归。在狀態(tài)A中夭坪,四種動作都會得到一個+10的收益,并且把智能體移動到A'过椎。在狀態(tài)B中室梅,四種動作都會得到一個+5的收益,并且把智能體移動到B‘疚宇。

image.png

2亡鼠、解析

這是一個典型的MDP問題,有限的狀態(tài)空間敷待,有限的動作空間间涵。但是,我們面臨兩個棘手的問題:

  • 根據Bellman等式榜揖,當前狀態(tài)的價值依賴于下一個狀態(tài)的價值浑厚,這是一個遞歸的過程股耽。從何處開始根盒,在何處結束钳幅?對于每一個狀態(tài)都有不同的episode。
  • 狀態(tài)空間和動作空間如何表達炎滞?狀態(tài)空間的表達容易想到使用格子的坐標來表示敢艰,比如格子A的狀態(tài)可表示為坐標0,10,1,那么動作空間如何表達比較合適呢册赛?

2.1钠导、Bellman等式的迭代求解

根據bellman求解MDP問題一般有兩種思路:第一,如果MDP的狀態(tài)轉移矩陣是已知的森瘪,則可以精確的數值求解:求解線性方程組而已牡属。。第二扼睬,Bellman等式本身是一個迭代公式逮栅,因此可以通過迭代的方式逐步逼近狀態(tài)價值函數。這種方式對狀態(tài)轉移矩陣不敏感窗宇,即無論是否知道狀態(tài)轉移矩陣都可以使用措伐,也非常適合于編程實現。

迭代求解狀態(tài)價值函數的基本步驟為:

  1. 初始化狀態(tài)價值矩陣军俊,一般初始化為0侥加。這是計算的起點,此時每個狀態(tài)的價值函數都是0粪躬。
  2. 根據Bellman等式担败,計算每個狀態(tài)的新的價值函數。注意這一步不是一個遞歸的過程镰官,因為上一輪的狀態(tài)價值矩陣是已知的提前,在這一輪直接可以根據上一輪的狀態(tài)價值矩陣計算新的價值函數即可,即:

v_{k+1}(s)=\sum_a \pi(a\mid s)\sum_{r,s'}p(s',r\mid s,a)\left[r+\gamma v_k(s')\right]

其中的k代表了迭代的輪次(episode)朋魔,注意不要和每個輪次(episode)中的時刻(步驟)的tt混淆了岖研。

計算每個輪次迭代的誤差,達到設定的誤差范圍即可停止迭代警检,此時即獲得了最終的狀態(tài)價值函數孙援。

這種迭代求解狀態(tài)價值函數的方法稱為”Policy Evaluation Prediction”诺核,即對于任意給定的策略\pi侄柔,都可以通過迭代的方式逐步逼近求解狀態(tài)價值函數兵拢。但是糊啡,必須確保這種迭代求解的方法對于任意策略\pi都是收斂的据沈,

證明如下:

通過觀察上式是鬼,并對照Bellman等式
v_{\pi}(s)=\sum_a \pi(a\mid s)\sum_{r,s'}p(s',r\mid s,a)\left[r+\gamma v_{\pi}(s')\right]
可以看出资铡,式1只是對式2的簡單變量替換鬼吵,由v_{\pi}替換為v_k,而式2在\gamma<1或者episode能夠在有限步內結束時即收斂鸽凶,因此式1在同樣的條件下也會收斂币砂,即迭代求解狀態(tài)價值函數的方法的收斂條件為:或者\gamma<1,或者所解決的MDP問題的episode是有限的玻侥。這兩個條件幾乎總是能夠滿足其中之一的决摧。

2.2、動作空間的表示方式

動作對狀態(tài)的影響表現為狀態(tài)坐標的改變凑兰,因此將動作定義為對狀態(tài)坐標的偏移量是個合理的方案掌桩,這樣可以直接將狀態(tài)和動作相加即可獲得“下一個狀態(tài)”。以動作up為例姑食,其對狀態(tài)的影響為橫坐標不變波岛,縱坐標增加+1,因此可以將up定義為[0,1]音半。同理则拷,動作down可以定義為[0,-1]。

3. 實現過程

3.1祟剔、導入庫文件

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.table import Table

3.2隔躲、定義環(huán)境

WORLD_SIZE = 5 # 定義問題中格子的數量
# 定義問題中A,A',B,B'的位置
A_POS = [0, 1] 
A_PRIME_POS = [4, 1]
B_POS = [0, 3]
B_PRIME_POS = [2, 3]
# 定義折扣參數
DISCOUNT = 0.9

# 把動作定義為對x,y坐標的增減改變
ACTIONS = [np.array([0, -1]), # 向上
           np.array([-1, 0]),  # 向左
           np.array([0, 1]),  # 向下
           np.array([1, 0])]  # 向右
# 定義畫圖會用到的動作
ACTIONS_FIGS=[ '←', '↑', '→', '↓']
# 該問題中每個動作選擇的概率為0.25
ACTION_PROB = 0.25

3.3物延、 定義環(huán)境轉移過程

def step(state, action):
    """每次走一步
    state:當前狀態(tài)宣旱,坐標的list,比如[1,1]
    action:當前采取的動作叛薯,是對狀態(tài)坐標的修正
    函數返回值浑吟,下一個狀態(tài)(坐標的list)和reward
    """
    # 當在A位置的時候,會轉移到A',并得到獎勵+10.
    if state == A_POS:
        return A_PRIME_POS, 10
    # 當在B位置的時候耗溜,會轉移到B',并得到獎勵+5.
    if state == B_POS:
        return B_PRIME_POS, 5
    
    # 計算下一個狀態(tài)
    next_state = (np.array(state) + action).tolist()
    x, y = next_state
    # 當運動未知超出格子世界則在原位置不變组力,并且得到-1的收益,其他情況得到的收益都是0抖拴。
    if x < 0 or x >= WORLD_SIZE or y < 0 or y >= WORLD_SIZE:
        reward = -1.0
        next_state = state
    else:
        reward = 0
    return next_state, reward

3.4 燎字、繪制價值函數結果

def draw_image(image):
    fig, ax = plt.subplots()
    ax.set_axis_off()
    tb = Table(ax, bbox=[0, 0, 1, 1])

    nrows, ncols = image.shape
    width, height = 1.0 / ncols, 1.0 / nrows

    # Add cells
    for (i, j), val in np.ndenumerate(image):

        # add state labels
        if [i, j] == A_POS:
            val = str(val) + " (A)"
        if [i, j] == A_PRIME_POS:
            val = str(val) + " (A')"
        if [i, j] == B_POS:
            val = str(val) + " (B)"
        if [i, j] == B_PRIME_POS:
            val = str(val) + " (B')"
        
        tb.add_cell(i, j, width, height, text=val,
                    loc='center', facecolor='white')
        
    # Row and column labels...
    for i in range(len(image)):
        tb.add_cell(i, -1, width, height, text=i+1, loc='right',
                    edgecolor='none', facecolor='none')
        tb.add_cell(-1, i, width, height/2, text=i+1, loc='center',
                    edgecolor='none', facecolor='none')

    ax.add_table(tb)

3.5 、繪制策略圖形

def draw_policy(optimal_values):
    fig, ax = plt.subplots()
    ax.set_axis_off()
    tb = Table(ax, bbox=[0, 0, 1, 1])

    nrows, ncols = optimal_values.shape
    width, height = 1.0 / ncols, 1.0 / nrows

    # Add cells
    for (i, j), val in np.ndenumerate(optimal_values):
        next_vals=[]
        for action in ACTIONS:
            next_state, _ = step([i, j], action)
            next_vals.append(optimal_values[next_state[0],next_state[1]])

        best_actions=np.where(next_vals == np.max(next_vals))[0]
        val=''
        for ba in best_actions:
            val+=ACTIONS_FIGS[ba]
        
        # add state labels
        if [i, j] == A_POS:
            val = str(val) + " (A)"
        if [i, j] == A_PRIME_POS:
            val = str(val) + " (A')"
        if [i, j] == B_POS:
            val = str(val) + " (B)"
        if [i, j] == B_PRIME_POS:
            val = str(val) + " (B')"
        
        tb.add_cell(i, j, width, height, text=val,
                loc='center', facecolor='white')

    # Row and column labels...
    for i in range(len(optimal_values)):
        tb.add_cell(i, -1, width, height, text=i+1, loc='right',
                    edgecolor='none', facecolor='none')
        tb.add_cell(-1, i, width, height/2, text=i+1, loc='center',
                   edgecolor='none', facecolor='none')

    ax.add_table(tb)

3.6阿宅、計算等概率隨機策略下的狀態(tài)價值函數(解貝爾曼期望方程)

貝爾曼期望方程的形式為:
v_{\pi}(s)=\sum_a \pi(a\mid s)\sum_{r,s'}p(s',r\mid s,a)\left[r+\gamma v_{\pi}(s')\right]

def figure_3_2():
    """
    計算每個單元格的狀態(tài)價值函數
    """
    # 狀態(tài)價值函數的初值設置為0
    value = np.zeros((WORLD_SIZE, WORLD_SIZE))
    while True:
        # # 每一輪迭代都會產生一個new_value候衍,直到new_value和value很接近即收斂為止
        new_value = np.zeros_like(value)
        
        # 對格子世界的每個狀態(tài)進行遍歷
        for i in range(WORLD_SIZE):
            for j in range(WORLD_SIZE):
                # 對每個狀態(tài)的4個動作進行遍歷
                for action in ACTIONS:
                    # 計算當前動作執(zhí)行后的下一個狀態(tài),以及獎勵
                    (next_i, next_j), reward = step([i, j], action)
                    # 由于每個方向只有一個reward和s'的組合洒放,這里的p(s',r|s,a)=1
                    new_value[i, j] += ACTION_PROB * (reward + DISCOUNT * value[next_i, next_j])
        # 當前new_value和value很接近蛉鹿,即error小到一定的程度則停止。
        error = np.sum(np.abs(new_value - value))
        if error < 1e-4:
            draw_image(np.round(new_value, decimals=2))
            plt.show()
            break
        value = new_value
figure_3_2()

輸出的測試結果如下所示:

image.png

可以看出往湿,靠近下邊的格子妖异,尤其是靠近邊界的格子的狀態(tài)價值偏小惋戏,這是因為靠近邊界的格子很容易出界,而出界的獎勵是-1他膳;格子A的價值最高响逢,這是很容易理解的,因為從A到A’的獎勵是+10矩乐。但是為什么格子A的價值<10呢龄句?這是因為從A到A’的獎勵盡管是+10,但是A’的價值卻是負值散罕,導致A的價值會跟著損失一些。格子B的價值分析方法類似傀蓉。

3.7欧漱、直接求解貝爾曼方程

下面采用代碼直接去求解貝爾曼方程。

def figure_3_2_linear_system():
    '''
    該函數通過直接求解線性方程組葬燎,得到貝爾曼方程的精確解误甚。
    Here we solve the linear system of equations to find the exact solution.
    We do this by filling the coefficients for each of the states with their respective right side constant.
    '''
    # 定義A矩陣,25*25大小谱净,對應著25個線性方程組
    A = -1 * np.eye(WORLD_SIZE * WORLD_SIZE)
    b = np.zeros(WORLD_SIZE * WORLD_SIZE)
    for i in range(WORLD_SIZE):
        for j in range(WORLD_SIZE):
            # 當前狀態(tài)
            s = [i, j]  
            # 該函數找到狀態(tài)s的序號窑邦,即將格子展開為5*5=25后,在這個長序列中的編號壕探。
            index_s = np.ravel_multi_index(s, (WORLD_SIZE, WORLD_SIZE))
            for a in ACTIONS:
                # 獲取執(zhí)行動作后的下一個狀態(tài)和獎勵
                s_, r = step(s, a)
                # 找到下一個狀態(tài)的序號
                index_s_ = np.ravel_multi_index(s_, (WORLD_SIZE, WORLD_SIZE))
               # 線性方程組Ax=b的A中對應元素按照動作概率*折扣因子進行更新
                A[index_s, index_s_] += ACTION_PROB * DISCOUNT
                b[index_s] -= ACTION_PROB * r
    # 求解Ax=b
    x = np.linalg.solve(A, b)
    draw_image(np.round(x.reshape(WORLD_SIZE, WORLD_SIZE), decimals=2))
    plt.show()

輸出過和通過迭代方式求解出來的結果是一致的冈钦。

image.png

3.8、求解最優(yōu)價值函數(解貝爾曼最優(yōu)方程)

貝爾曼最優(yōu)方程的形式為:
\begin{aligned} q_{*}(s,a)& =\mathbb E[R_{t+1}+\gamma \max_{a'}q_*(S_{t+1},a')\mid S_t=s, A_t=a] \\ &=\sum_{s',r}p(s',r \mid s,a)[R_{t+1}+\gamma \max_{a'}q_*(S_{t+1},a')] \end{aligned}

def figure_3_5():
    '''
    求解貝爾曼最優(yōu)方程
    '''
    # 初始值設為0
    value = np.zeros((WORLD_SIZE, WORLD_SIZE))
    while True:
        # keep iteration until convergence
        new_value = np.zeros_like(value)
        # 遍歷所有狀態(tài)
        for i in range(WORLD_SIZE):
            for j in range(WORLD_SIZE):
                values = []
                # 遍歷所有動作
                for action in ACTIONS:
                    # 執(zhí)行動作,轉移到后繼狀態(tài),并獲得立即獎勵
                    (next_i, next_j), reward = step([i, j], action)
                    # value iteration
                   # 緩存動作值函數 q(s,a) = r + γv(s')
                    values.append(reward + DISCOUNT * value[next_i, next_j])
                # 根據貝爾曼最優(yōu)方程,找出最大的動作值函數 q(s,a) 進行更新
                new_value[i, j] = np.max(values)
        # 迭代終止條件: 誤差小于1e-4
        if np.sum(np.abs(new_value - value)) < 1e-4:
            draw_image(np.round(new_value, decimals=2))
            plt.show()
            plt.close()
            draw_policy(new_value)
            plt.show()
            break
        value = new_value
figure_3_5()

計算得到的最優(yōu)價值函數如下所示:

image.png

從最后價值函數得到的最優(yōu)策略如下李请,圖中有很多個箭頭瞧筛,其對應的每個動作都是最優(yōu)的。

image.png
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末导盅,一起剝皮案震驚了整個濱河市较幌,隨后出現的幾起案子,更是在濱河造成了極大的恐慌白翻,老刑警劉巖乍炉,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異滤馍,居然都是意外死亡岛琼,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門纪蜒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衷恭,“玉大人,你說我怎么就攤上這事纯续∷嬷椋” “怎么了灭袁?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窗看。 經常有香客問我茸歧,道長,這世上最難降的妖魔是什么显沈? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任软瞎,我火速辦了婚禮,結果婚禮上拉讯,老公的妹妹穿的比我還像新娘涤浇。我一直安慰自己,他們只是感情好魔慷,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布只锭。 她就那樣靜靜地躺著,像睡著了一般院尔。 火紅的嫁衣襯著肌膚如雪蜻展。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天邀摆,我揣著相機與錄音纵顾,去河邊找鬼。 笑死栋盹,一個胖子當著我的面吹牛施逾,可吹牛的內容都是我干的。 我是一名探鬼主播贞盯,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼音念,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了躏敢?” 一聲冷哼從身側響起闷愤,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎件余,沒想到半個月后讥脐,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡啼器,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年旬渠,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片端壳。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡告丢,死狀恐怖,靈堂內的尸體忽然破棺而出损谦,到底是詐尸還是另有隱情岖免,我是刑警寧澤岳颇,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站颅湘,受9級特大地震影響话侧,放射性物質發(fā)生泄漏。R本人自食惡果不足惜闯参,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一瞻鹏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鹿寨,春花似錦新博、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至玩讳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間嚼贡,已是汗流浹背熏纯。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留粤策,地道東北人樟澜。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像叮盘,于是被迫代替她去往敵國和親秩贰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359