強化學習 Q學習原理及例子(離散)附matlab程式
假設我們的樓層內共有5個房間,房間之間通過一道門相連,正如下圖所示。我們將房間編號為房間0到房間4,樓層的外部可以被看作是一間大房間,編號為5。注意到房間1和房間4可以直接通到房間5。
我們可以用圖來表示上述的房間,將每一個房間看作是一個節點,每一道門看作是一條邊(鏈路)。
當然,從房間5到房間5的獎勵值也是100,其他所有直接通到目標房間5的獎勵值也是100。在Q-學習中,學習的目標是達到具有最高獎勵值的狀態,因此,如果智慧體到底了目標位置,它將永遠的留在那兒。這種型別的目標被稱為“吸收目標”。
想象我們的智慧體是一個不會說話的虛擬機器器人,但是它可以從經驗中學習。智慧體能夠從一個房間到底另外一個房間,但是它對周圍的環境一無所知,它不知道怎麼走能夠通到樓層外面(房間5)。
假設我們想對智慧體從某一個房間中撤退的過程進行建模,現在,我們假設智慧體在房間2內,我們希望智慧體通過學習到達房間5。
Q-學習中的術語包括狀態(state)和動作(action)。
我們將每一個房間稱為一個“狀態”,智慧體從一個房間到另一個房間的移動過程稱為“動作”。在我們的示意圖中,狀態被描述為節點,動作被描述成箭頭。
假設智慧體處於狀態2,那麼,它從狀態2能夠直接到達狀態3,因為狀態2和狀態3相連。然而,智慧體從狀態2不能直接到達狀態1,因為在房間2和房間1之間沒有直接相通的門,也即沒有箭頭存在。從狀態3,智慧體要麼到達狀態1,要麼到達狀態4,抑或著返回到狀態2。如果智慧體處於狀態4,那麼它有3周可能的動作,即到達狀態0,、5或3。如果智慧體在狀態1,它能夠到達狀態5或者狀態3。從狀態0,它只能到達狀態4。
我們可以將狀態圖和即時獎勵值填入到下面的獎勵表中,即矩陣R: (表中的-1代表空值,表示節點之間無邊相連)
現在,我們再增加一個相似的矩陣Q,代表智慧體從經驗中所學到的知識。矩陣Q的行代表智慧體當前的狀態,列代表到達下一個狀態的可能的動作。
因為智慧體在最初對環境一無所知,因此矩陣Q被初始化為0。在這個例子中,為了闡述方便,我們假設狀態的數量是已知的(設為6)。如果我們不知道有多少狀態時,矩陣Q在最初被設為只有一個元素。如果新的狀態一旦被發現,對矩陣Q增加新的行和新的列非常簡單。
Q-學習的轉換規則非常簡單,為下面的式子:
Q(state, action)=R(state, action) + Gamma * Max(Q[next state, all actions])
依據這個公式,矩陣Q中的一個元素值就等於矩陣R中相應元素的值與學習變數Gamma乘以到達下一個狀態的所有可能動作的最大獎勵值的總和。
我們虛擬的智慧體將從經驗中學習,不需要教師指導訊號(這被稱為非監督學習)。智慧體將從一個狀態到另一個狀態進行探索,直到它到達目標狀態。我們將每一次探索作為一次經歷,每一次經歷包括智慧體從初始狀態到達目標狀態的過程。每次智慧體到達了目標狀態,程式將會轉向下一次探索。
Q-學習演算法的計算過程如下:
1、設定引數Gamma,以及矩陣R中的環境獎勵值;
2、初始化Q矩陣為0;
3、對每一次經歷:
隨機選擇一個狀態;
Do while 目標狀態未到達
對當前狀態的所有可能的動作中,選擇一個可能的動作;
使用這個可能的動作,到達下一個狀態;
對下一個狀態,基於其所有可能的動作,獲得最大的Q值;
計算:Q(state, action)=R(state, action) + Gamma * Max(Q[next state, all actions])
設定下一個狀態作為當前狀態;
End For
智慧體利用上述的演算法從經驗中學習,每一次經歷等價於一次訓練。在每一次訓練中,智慧體對環境進行探索(用矩陣R表示),並且其一旦到達目標狀態,就得到獎勵值。訓練的目的是增強智慧體的大腦,用矩陣Q表示。越多的訓練結果將導致更優的矩陣Q。在這種情況下,如果矩陣Q已經被增強,那麼智慧體就不會四處盲目的探索,而是會找到最快的路線到達目標狀態。
引數Gamma的取值在0到1之間(0<=Gamma<=1),如果Gamma越接近於0,智慧體更趨向於僅僅考慮即時獎勵;如果Gamma更接近於1,智慧體將以更大的權重考慮未來的獎勵,更願意將獎勵延遲。
為了使用矩陣Q,智慧體僅僅簡單地跟蹤從起始狀態到目標狀態的狀態序列,這個演算法在矩陣Q中,為當前狀態尋找到具有最高獎勵值的動作。
利用矩陣Q的演算法如下:
1、設定當前狀態=初始狀態;
2、從當前狀態開始,尋找具有最高Q值的動作;
3、設定當前狀態=下一個狀態;
4、重複步驟2和3,直到當前狀態=目標狀態。
上述的演算法將返回從初始狀態到目標狀態的狀態序列。
為了理解Q-學習演算法是怎樣工作的,我們通過分析少量的例子進行分析。
我們設定學習率Gamma等於0.8,初始的狀態是房間1。
初始的矩陣Q作為一個零矩陣,如下:
觀察R矩陣的第二行(狀態1),對狀態1來說,存在兩個可能的動作:到達狀態3,或者到達狀態5。通過隨機選擇,我們選擇到達狀態5。 現在,讓我們想象如果我們的智慧體到達了狀態5,將會發生什麼?觀察R矩陣的第六行,有3個可能的動作,到達狀態1,4或者5。
Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)]
Q(1, 5) = R(1, 5) + 0.8 * Max[Q(5, 1), Q(5, 4), Q(5, 5)] = 100 + 0.8 * 0 = 100
由於矩陣Q此時依然被初始化為0,Q(5, 1), Q(5, 4), Q(5, 5)全部是0,因此,Q(1, 5)的結果是100,因為即時獎勵R(1,5)等於100。
下一個狀態5現在變成了當前狀態,因為狀態5是目標狀態,因此我們已經完成了一次嘗試。我們的智慧體的大腦中現在包含了一個更新後的Q矩陣。 對於下一次訓練,我們隨機選擇一個初始狀態,這一次,我們選擇狀態3作為我們的初始狀態。
觀察R矩陣的第4行,有3個可能的動作,到達狀態1,2和4。我們隨機選擇到達狀態1作為當前狀態的動作。
現在,我們想象我們在狀態1,觀察矩陣R的第2行,具有2個可能的動作:到達狀態3或者狀態5。現在我們計算Q值:
Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)]
Q(3, 1) = R(3, 1) + 0.8 * Max[Q(1, 2), Q(1, 5)] = 0 + 0.8 * Max(0, 100) = 80
我們使用上一次嘗試中更新的矩陣Q得到:Q(1, 3) = 0 以及 Q(1, 5) = 100。因此,計算的結果是Q(3,1)=80,因為獎勵值為0。現在,矩陣Q變為:
下一個狀態1變成了當前狀態,我們重複Q學習演算法中的內部迴圈過程,因為狀態1不是目標狀態。
因此,我們從當前狀態1開始一次新的迴圈,此時有2個可能的動作:到達狀態3或者狀態5。我們幸運地選擇到達了狀態5。
現在,想象我們處於狀態5,有3個可能的動作:到達狀態1,4或5。我們計算Q值如下:
Q(state, action) = R(state, action) + Gamma * Max[Q(next state, all actions)]
Q(1, 5) = R(1, 5) + 0.8 * Max[Q(5, 1), Q(5, 4), Q(5, 5)] = 100 + 0.8 * 0 = 100
更新後的矩陣Q中,Q(5, 1), Q(5, 4), Q(5, 5)依然是0,故Q(1, 5)的值是100,因為即時獎勵R(5,1)是100,這並沒有改變矩陣Q。
因為狀態5是目標狀態,我們完成了這次嘗試。我們的智慧體大腦中包含的矩陣Q更新為如下所示:
如果我們的智慧體通過多次的經歷學到了更多的知識,Q矩陣中的值會達到一收斂狀態,如下:
通過對Q中所有的非零值縮小一定的百分比,可以對其進行標準化,結果如下: 一旦矩陣Q接近於收斂狀態,我們就知道智慧體已經學習到了到達目標狀態的最佳路徑。 例如,從初始狀態2,智慧體在矩陣Q的指導下進行移動:
在狀態2時,由矩陣Q中最大的值可知下一個動作應該是到達狀態3;
在狀態3時,矩陣Q給出的建議是到達狀態1或者4,我們任意選擇,假設選擇了到達狀態1;
在狀態1時,矩陣Q建議到達狀態5;
因此,智慧體的移動序列是2-3-1-5。
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Q learning of single agent move in N rooms
% Matlab Code companion of
% Q Learning by Example
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function q=ReinforcementLearning
clc;
format short
format compact
% Two input: R and gamma
% immediate reward matrix;
% row and column = states; -Inf = no door between room
R=[-inf,-inf,-inf,-inf, 0, -inf;
-inf,-inf,-inf, 0,-inf, 100;
-inf,-inf,-inf, 0,-inf, -inf;
-inf, 0, 0,-inf, 0, -inf;
0,-inf,-inf, 0,-inf, 100;
-inf, 0,-inf,-inf, 0, 100];
gamma=0.80; % learning parameter
q=zeros(size(R)); % initialize Q as zero,q的行數和列數等於矩陣R的。
q1=ones(size(R))*inf; % initialize previous Q as big number
count=0; % counter
for episode=0:50000
% random initial state
y=randperm(size(R,1));%產生1到6的隨機數%a=size(R,1)把矩陣R的行數返回給a,b=size(R,2)把矩陣R的列數返回給b
state=y(1); %取1到6的隨機數的第一個數
% select any action from this state
x=find(R(state,:)>=0); % find possible action of this state.返回矩陣R第state行所有列中不小於零的資料的下標
if size(x,1)>0,
x1=RandomPermutation(x); % randomize the possible action
x1=x1(1); % select an action
end
qMax=max(q,[],2);
q(state,x1)= R(state,x1)+gamma*qMax(x1); % get max of all actions
% break if convergence: small deviation on q for 1000 consecutive
if sum(sum(abs(q1-q)))<0.0001 & sum(sum(q >0))
if count>1000,
episode % report last episode
break % for
else
count=count+1; % set counter if deviation of q is small
end
else
q1=q;
count=0; % reset counter when deviation of q from previous q is large
end
end
%normalize q
g=max(max(q));
if g>0,
q=100*q/g;
end
% The code above is using basic library RandomPermutation below
function y=RandomPermutation(A)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% return random permutation of matrix A
% unlike randperm(n) that give permutation of integer 1:n only,
% RandomPermutation rearrange member of matrix A randomly
% This function is useful for MonteCarlo Simulation,
% Bootstrap sampling, game, etc.
%
% Copyright Kardi Teknomo(c) 2005
% (http://people.revoledu.com/kardi/)
%
% example: A = [ 2, 1, 5, 3]
% RandomPermutation(A) may produce [ 1, 5, 3, 2] or [ 5, 3, 2, 3]
%
% example:
% A=magic(3)
% RandomPermutation(A)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[r,c]=size(A);
b=reshape(A,r*c,1); % convert to column vector
x=randperm(r*c); % make integer permutation of similar array as key
w=[b,x']; % combine matrix and key
d=sortrows(w,2); % sort according to key
y=reshape(d(:,1),r,c); % return back the matrix