一个Q_learning代码的简明教程实现

来源:互联网 发布:淘宝店怎么添加音乐 编辑:程序博客网 时间:2024/06/07 03:20

Flappy Bird

在浏览机器学习相关内容的时候,看到有人通过机器学习玩转一个曾经很火的手机游戏Flappy bird。 其使用的算法是Q_learning。
这里写图片描述

算法如下:

状态矢量空间
在这里一共设计了3个参数:1,小鸟与低管道的垂直距离;2,小鸟与下一个管道出口的水平距离;3,小鸟是否死亡。
行为
对每个状态,我设计了两个可能存在的行为:点击或者是什么都不做。
奖励
奖励完全依赖于“Life”参数,仍然存活则+1,失败则-1000。
学习循环
数组Q初始化为0,同时也总采取最佳操作,这些操作将最大化我的预期奖励。
第一步,观察Flappy Bird所处的状态,并执行可以最大化预期奖励的操作。让游戏引擎执行“tick”操作,随之Flappy Bird进入下一个状态s’。
第二步,观察s’及状态下的奖励,+1则表示小鸟还活着。
第三步,通过Q Learning规则来修改Q数组。Alpha的值被设置成0.7,因为我们需要一个确定的状态,也让学习的可能最大化;同时,Y和lambda都被设置成了1。
第四步,将当前状态设置为s’并重新开始。

原文链接:Flappy Bird hack using Reinforcement Learning
译文链接:亚特兰大极客使用机器学习玩转Flappy Bird

对其所利用的Q_learning进行资料搜索,找到一个简明的教程对Q_Learning进行了介绍。

一个简明教程

具体的教程见链接A Painless Q-learning Tutorial
其解决的问题:利用无监督训练让代理找到走出房间的路线。
这里写图片描述

C++代码

#include <iostream>#include<cstring>#include<cmath>#include <cstdlib>using namespace std;#define ROW    6#define COLUMN 6#define STATE_NUM 6#define ACTION_NUM 6#define alph 0.8float a[100][100];float b[100][100];/*R(s,a),目标函数*/float R[100][100]={{-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(s,a),学习函数,初始化为0*/float Q[100][100];/*初始化的顺序*/int initial_can_go[10];//存储可以做的actionint a_can_go[10];//存储可以做的actionint NUM=0;/*R*/void get_go_value(float a[100][100],int can_go[10],int state){    NUM=0;    for(int i=0;i<ACTION_NUM;i++)    {        if(a[state][i]>=0)        {            can_go[NUM]=i;            NUM++;        }    }}float get_max_value(float Q[100][100],int state){    float tempmax=0;    for(int i=0;i<ACTION_NUM;i++)    {        if((R[state][i]>=0)&&(Q[state][i]>tempmax))            tempmax=Q[state][i];    }    return tempmax;}int get_max_tab(float Q[100][100],int state){    float tempmax=0;    int temptab=0;    for(int i=0;i<ACTION_NUM;i++)    {        if((Q[state][i]>tempmax))        {            tempmax=Q[state][i];            temptab=i;        }    }    return temptab;}/*initial:初始状态*/int learning_G(int initial, float R[100][100],float Q[100][100],int flag){    float Q_before,Q_new;    int a;   //是端点    float a_2;//是回报值,非端点    memset(initial_can_go,0,10*sizeof(int));    get_go_value(R,initial_can_go,initial);//返回了端点和num    a=initial_can_go[rand()%NUM];    a_2=get_max_value(Q,a);    /*initial_can_go数组存放了可以进行的动作*/    /*a为随机进行的当前action*/    /*a_2为该action下的最大反馈*/    /*被更新的是Q(initial,a)*/    Q_before=Q[initial][a];    Q[initial][a]=R[initial][a]+alph*a_2;    Q_new=Q[initial][a];    if(Q_before==Q_new) flag++;    else flag=0;    if(flag==50)     return 0;    if(Q_new == 100) initial=rand()%STATE_NUM;    else       initial=a;    cout<<"initial="<<initial<<endl;    learning_G(initial,R,Q,flag);}int main(){    cout<<"****************R矩阵****************"<<endl;    for(int i=0; i<STATE_NUM; i++)    {        for(int j=0; j<ACTION_NUM; j++)        {            cout <<R[i][j]<<"\t";        }        cout<<endl;    }    cout<<"**************Q矩阵*******************"<<endl;    for(int i=0; i<STATE_NUM; i++)    {        for(int j=0; j<ACTION_NUM; j++)        {            cout <<Q[i][j]<<"\t";        }        cout<<endl;    }    int flag=0;    int initial=1;    cout<<"initial="<<initial<<endl;    learning_G(initial,R,Q,flag);    cout<<"**************shoulianjuzhen**********"<<endl;    for(int i=0; i<STATE_NUM; i++)    {        for(int j=0; j<ACTION_NUM; j++)        {            cout <<Q[i][j]<<"\t";        }        cout<<endl;    }    int position;    while(1){        cout<<"please input<<";        cin>>position;        cout<<position<<"->";        while(1)        {            int j=get_max_tab(Q,position);            cout<<j<<"->";            if(R[position][j]==100)            {                cout<<"out"<<endl;                break;            }            else                position=j;        }    }    return 0;}

运行后得到的收敛矩阵

这里写图片描述

附:

抱歉,写的代码和注释有点乱,两个月前写的代码,现在自己都快忘了。下次有空了再整理。

0 0
原创粉丝点击