在浏览机器学习相关内容的时候,看到有人通过机器学习玩转一个曾经很火的手机游戏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
其解决的问题:利用无监督训练让代理找到走出房间的路线。
#include
#include
#include
#include
using namespace std;
#define ROW 6
#define COLUMN 6
#define STATE_NUM 6
#define ACTION_NUM 6
#define alph 0.8
float 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];//存储可以做的action
int a_can_go[10];//存储可以做的action
int NUM=0;
/*R*/
void get_go_value(float a[100][100],int can_go[10],int state)
{
NUM=0;
for(int i=0;iif(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;iif((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;iif((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="<int main()
{
cout<<"****************R矩阵****************"<for(int i=0; ifor(int j=0; jcout <"\t";
}
cout<cout<<"**************Q矩阵*******************"<for(int i=0; ifor(int j=0; jcout <"\t";
}
cout<int flag=0;
int initial=1;
cout<<"initial="<cout<<"**************shoulianjuzhen**********"<for(int i=0; ifor(int j=0; jcout <"\t";
}
cout<int position;
while(1){
cout<<"please input<<";
cin>>position;
cout<"->";
while(1)
{
int j=get_max_tab(Q,position);
cout<"->";
if(R[position][j]==100)
{
cout<<"out"<break;
}
else
position=j;
}
}
return 0;
}
抱歉,写的代码和注释有点乱,两个月前写的代码,现在自己都快忘了。下次有空了再整理。