1. 程式人生 > >強化學習 Q學習原理及例子(離散)附matlab程式

強化學習 Q學習原理及例子(離散)附matlab程式

原文地址:http://mnemstudio.org/path-finding-q-learning-tutorial.htm 這篇教程通過簡單且易於理解的例項介紹了Q-學習的概念知識,例子描述了一個智慧體通過非監督學習的方法對未知的環境進行學習。
假設我們的樓層內共有5個房間,房間之間通過一道門相連,正如下圖所示。我們將房間編號為房間0到房間4,樓層的外部可以被看作是一間大房間,編號為5。注意到房間1和房間4可以直接通到房間5。

我們可以用圖來表示上述的房間,將每一個房間看作是一個節點,每一道門看作是一條邊(鏈路)。
在這個例子中,我們可能在任意一間房間中放置一個智慧體(機器人),並期望該智慧體能夠從該房間開始走出這棟樓(可以認為是我們的目標房間)。換句話說,智慧體的目的地是房間5。為了設定這間房間作為目標,我們為每一道門(節點之間的邊)賦予一個獎勵值。能夠直接通到目標房間的門賦予一及時獎勵值100,而其他的未與目標房間直接相連的門賦予獎勵值0。因為每一道門都有兩個方向,因此,每一道門在圖中將描述為兩個箭頭。如下所示:
當然,從房間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