Press "Enter" to skip to content

强化学习简单示例——SARSA算法

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

【注】我也是刚刚接触强化学习的内容,对这部分理解不是很透彻,代码写的可能也会有不对或不完善的地方,还请各位批评指正。这个问题是个作业,这是我自己编的代码,老师提供的答案出来后再更。

 

【问题描述】

 

 

图中S为起点,G为终点,每次能前、后、左、右、左前、左后、右前、右后移动。当到达第4-9列的某一列时,会在某一状态的基础上向上被吹一格。如某一时刻到达了第4行第4列,则会被吹到第3行第4列。在第4行第7列则会被吹到第2行第7列。设每步的reward都为-1,无折扣,更新步长α为0.1,对于所有状态s和动作a,初始值函数Q(s,a)=0,ε-greedy方法的ε=0.1,求起点到终点的最优路径。

 

【思路】

 

将每个状态标号,从左到右,从上到下,为1-70。从起点S状态开始,用SARSA算法更新每个状态-动作的值函数Q,策略选择ε-greedy方法,直到到达终点G。这为一条完整的采样,再循环以上过程N次,N可以为2000、5000、10000等等,越大越接近真实值。最后得到完整的值函数Q表,从起点开始,每步选择使Q最大的动作,直到终点G,走过的路径即为最优路径。

 

【源代码】

 

1、SARSA.m

 

%SARSA求KING'MOVING问题
%
a=0.1;                  %更新步长
loops_num=2000;         %循环次数,自己设定,越大值函数越逼近真实值
reward=-1;              %奖赏,总为-1
global qMatrix;         %定义值函数矩阵
qMatrix=zeros(70,70);   %值函数矩阵赋值,初始全为0
routeMatrix=-1./zeros(7,10);   %定义行走路径矩阵,负无穷表示不走此路,0表示走此路
star_state=31;           %初始状态
final_state=38;          %终止状态
count=0;
epiosdes=[];
%SARSA算法更新值函数
for i=1:1:loops_num
    state=star_state;     
    action=select_action(state);     %选择当前状态下的动作
    while (1)      
        statep=action;                      %下个状态     
        actionp=select_action(statep);      %选择动作达到的状态下的动作
        qMatrix(state,action)=qMatrix(state,action)+a*(-1+qMatrix(statep,actionp)-qMatrix(state,action));      %更新值函数       
        state=statep;
        action=actionp;
        if(state==38)   break;   end     %如果到终点则退出
        count=count+1;
        epiosdes(count)=i;
    end  
%    count=count+1;
end
%找最优路径
state=star_state;
while(1)
    [val,action]=min(1./qMatrix(state,:));      %根据值函数最大,找下一个动作
    %将下个动作达到的状态设为可行走
    row=floor(action/10)+1;
    clo=action-(row-1)*10;
    routeMatrix(row,clo)=0;
    %将当前状态设为可行走
    row=floor(state/10)+1;
    clo=state-(row-1)*10;
    routeMatrix(row,clo)=0;        
    if(action==38)   break;  end          %到达终点,退出
    state=action;                         %将动作赋给状态
end
plot(1:1:count,epiosdes);   xlabel('Time steps');   ylabel('episodes');

 

2、selsect_action.m

 

%选择动作函数,用e-greedy算法
function[action_sel]=select_action(aa)
    actionMatrix=[11,10,9,1,-1,-9,-10,-11];    %定义动作,即8个方向
    max=-1000;    %要尽量小
    max_num=0;
    e=0.1;        %e-greedy算法的概率   
    global qMatrix;
    action_sel=0;
    action_maybe=[-1,-1,-1,-1,-1,-1,-1,-1];      %aa状态周围可能的状态,初始-1.-1代表没有此状态
    for i=1:1:8                                  %aa状态周围可能的状态
        action_maybe(i)=aa-actionMatrix(i);        
    %添加有风的情况
    row=floor(action_maybe(i)/10)+1;
    clo=action_maybe(i)-(row-1)*10;
    %向上吹一格的情况
    if(((clo>=4)&(clo<=6))|(clo==9))
        if(row>=2&&row<=7)     action_maybe(i)=action_maybe(i)-10; end      
    end
    %向上吹两格的情况
    if((clo==7)|(clo==8))
        if(row>=3&&row<=7)    action_maybe(i)=action_maybe(i)-20;  
        else if(row==2)     action_maybe(i)=action_maybe(i)-10;    end 
        end
    end            
    end
    %排除边角不能走的情况
    if(aa==1)    action_maybe(1:4)=-1;   action_maybe(6)=-1;   end
    if(aa==10)    action_maybe(1:3)=-1;   action_maybe(5)=-1;   action_maybe(8)=-1;  end
    if(aa==61)    action_maybe(6:8)=-1;   action_maybe(1)=-1;   action_maybe(4)=-1;  end
    if(aa==70)    action_maybe(5:8)=-1;   action_maybe(3)=-1;   end
    if(aa>=2&&aa<=9)   action_maybe(1:3)=-1;    end
    if(aa>=62&&aa<=69)   action_maybe(6:8)=-1;    end
    if(aa==11||aa==21||aa==31||aa==41||aa==51)    action_maybe(1)=-1;    action_maybe(4)=-1;   action_maybe(6)=-1;  end
    if(aa==20||aa==30||aa==40||aa==50||aa==60)    action_maybe(3)=-1;    action_maybe(5)=-1;   action_maybe(8)=-1;  end        
    r=rand();    %生成随机数
    if(r>e)       %大于e,则选择值函数最大的动作
        for i=1:1:8
            if(action_maybe(i)~=-1)
%                row=floor(action_maybe(i)/10);
%                clo=action_maybe(i)-row*10;
                if(qMatrix(aa,action_maybe(i))>=max)
                    max=qMatrix(aa,action_maybe(i));   max_num=i; end
            end           
        end
        action_sel=action_maybe(max_num);
    else          %小于e,则随机选取动作
        while(1)          
            rr=floor(rand(1)*8)+1;       %生成1-8的随机整数
            action_sel=action_maybe(rr);
            if (action_sel~=-1)   break;  end 
        end         
    end 
end

 

【运行结果】

 

循环2000次,即2000条采样路径。0表示走过的路径:

 

 

times steps和episodes的关系曲线。横轴为整个程序走过的累计步数,纵轴含义为走了那幺多步时,当前处于第几条采样路径上。

 

Be First to Comment

发表回复

您的电子邮箱地址不会被公开。