1. 程式人生 > >強化學習-Q-learning

強化學習-Q-learning

原文:https://www.jianshu.com/p/29db50000e3f?utm_medium=hao.caibaojian.com&utm_source=hao.caibaojian.com

1、Q-learning例子

假設有這樣的房間

如果將房間表示成點,然後用房間之間的連通關係表示成線,如下圖所示:

這就是房間對應的圖。我們首先將agent(機器人)處於任何一個位置,讓他自己走動,直到走到5房間,表示成功。為了能夠走出去,我們將每個節點之間設定一定的權重,能夠直接到達5的邊設定為100,其他不能的設定為0,這樣網路的圖為:

Qlearning中,最重要的就是“狀態”和“動作”,狀態表示處於圖中的哪個節點,比如2節點,3節點等等,而動作則表示從一個節點到另一個節點的操作。

首先我們生成一個獎勵矩陣矩陣,矩陣中,-1表示不可以通過,0表示可以通過,100表示直接到達終點:

同時,我們建立一個Q表,表示學習到的經驗,與R表同階,初始化為0矩陣,表示從一個state到另一個state能獲得的總的獎勵的折現值。

image.png

Q表中的值根據如下的公式來進行更新:

在上面的公式中,S表示當前的狀態,a表示當前的動作,s表示下一個狀態,a表示下一個動作,λ為貪婪因子,0<λ<1,一般設定為0.8。Q表示的是,在狀態s下采取動作a能夠獲得的期望最大收益,R是立即獲得的收益,而未來一期的收益則取決於下一階段的動作。

所以,Q-learning的學習步驟可以歸結為如下:

在迭代到收斂之後,我們就可以根據Q-learning來選擇我們的路徑走出房間。
看一個實際的例子,首先設定λ=0.8,獎勵矩陣R和Q矩陣分別初始化為:

隨機選擇一個狀態,比如1,檢視狀態1所對應的R表,也就是1可以到達3或5,隨機地,我們選擇5,根據轉移方程:

於是,Q表為:

這樣,到達目標,一次嘗試結束。
接下來再選擇一個隨機狀態,比如3,3對應的下一個狀態有(1,2,4都是狀態3對應的非負狀態),隨機地,我們選擇1,這樣根據演算法更新:

這樣,Q表為:

經過不停的迭代,最終我們的Q表為:

我們不妨將Q表中的數轉移到我們一開始的示意圖中:

在得到Q表之後,我們可以根據如下的演算法來選擇我們的路徑:

舉例來說,假設我們的初始狀態為2,那麼根據Q表,我們選擇2-3的動作,然後到達狀態3之後,我們可以選擇1,2,4。但是根據Q表,我們到1可以達到最大的價值,所以選擇動作3-1,隨後在狀態1,我們按價值最大的選擇選擇動作1-5,所以路徑為2-3-1-5.

2、程式碼實現

上面的例子可以用下面的程式碼來實現,非常的簡單,直接貼上完整的程式碼吧:

import numpy as np
import random

r = np.array([[-1, -1, -1, -1, 0, -1], [-1, -1, -1, 0, -1, 100], [-1, -1, -1, 0, -1, -1], [-1, 0, 0, -1, 0, -1],
              [0, -1, -1, 0, -1, 100], [-1, 0, -1, -1, 0, 100]])

q = np.zeros([6,6],dtype=np.float32)

gamma = 0.8

step = 0
while step < 1000:
    state = random.randint(0,5)
    if state != 5:
        next_state_list=[]
        for i in range(6):
            if r[state,i] != -1:
                next_state_list.append(i)
        next_state = next_state_list[random.randint(0,len(next_state_list)-1)]
        qval = r[state,next_state] + gamma * max(q[next_state])
        q[state,next_state] = qval

print(q)

print(q)
# 驗證

for i in range(10):
    print("第{}次驗證".format(i + 1))
    state = random.randint(0, 5)
    print('機器人處於{}'.format(state))
    count = 0
    while state != 5:
        if count > 20:
            print('fail')
            break
        # 選擇最大的q_max
        q_max = q[state].max()

        q_max_action = []
        for action in range(6):
            if q[state, action] == q_max:
                q_max_action.append(action)

        next_state = q_max_action[random.randint(0, len(q_max_action) - 1)]
        print("the robot goes to " + str(next_state) + '.')
        state = next_state
        count += 1

程式碼的輸出為:

 

參考資料:
http://mnemstudio.org/path-finding-q-learning-tutorial.htm
https://www.zhihu.com/question/26408259
https://zhuanlan.zhihu.com/p/29213893