最简单的机器学习例子——划拳游戏

    本文通过参考《强化学习与深度学习 C 语言模拟》一书,来说明机器学习的原理。

    进入正题,首先以一个划拳游戏来引入今天的主角——机器学习,剪刀石头布,相信大家伙都应该玩过,没有玩过的请教度娘,或关掉当前的网页。

   程序代码比较简单,如下:

/* Visual Studio兼容性 */
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>

#define SEED	65535   /* 随机数SEED */
#define GU		0  /* 石头 */
#define CYOKI   1  /* 剪刀 */
#define PA      2  /* 布 */
#define WIN     1  /* 胜 */
#define LOSE    -1  /* 负 */
#define DRAW     0  /* 平 */
#define ALPHA    0.01  /* 学习系数 */

/* 函数声明 */
int hand(double rate[]);
double frand(void);

int main()
{
	int n = 0;	/* 对战次数的计数器 */
	int myhand, ohand;  	/* 自己的出拳和对手的出拳 */
	double rate[3] = {1, 1, 1};   	/* 出拳比率 */
	int gain;  	/* 胜负结果 */
	int payoffmatrix[3][3] = {{DRAW, WIN, LOSE},   	/* 胜负矩阵 */
	{LOSE, DRAW, WIN},
	{WIN, LOSE, DRAW}};

	while (scanf("%d", &ohand) != EOF)
	{
		if (ohand < GU || ohand > PA)  	/* 出拳不合法 */
		{
			continue;
		}

		myhand = hand(rate);   	/* 按照出拳比例进行出拳 */
		gain = payoffmatrix[myhand][ohand];  	/* 胜负判断 */
		printf("%d %d %d ", myhand, ohand, gain);  	/* 输出结果 */
		rate[myhand] += gain*ALPHA*rate[myhand];  	/* 学习出拳比例 */
		printf("%1f, %1f, %1f\n", rate[GU], rate[CYOKI], rate[PA]);  /* 出拳比例输出 */
	}

	return 0;
}
/************************************************************************/
/*    hnad() 函数                                                        */
/*    随机数和其它参数一起出拳                                                */
/************************************************************************/
int hand(double rate[])
{
	double gu, cyoki, pa; /* 出拳的对应值 */
	gu = rate[GU]*frand();
	cyoki = rate[CYOKI]*frand();
	pa = rate[PA]*frand();

	if(gu > cyoki)
	{
		if(gu>pa) return GU;  /* gu大 */
		else return PA;  /* pa大 */
	}
	else
	{
		if(cyoki>pa) return CYOKI;  /* cyoki大 */
		else return PA;  /* pa大 */
	}
}

/************************************************************************/
/*    frand() 函数                                                        */
/*     0 - 1 的随机数                                                   */
/************************************************************************/
double frand(void)
{
	return (double)rand()/RAND_MAX;
}

  话不多说,接下来,直接分析程序。

 以下代码时得出模型的出拳类型,其中数组 rate 保存的是模型的出拳比率。初始化为 1 : 1 : 1。

	double gu, cyoki, pa; /* 出拳的对应值 */
	gu = rate[GU]*frand();
	cyoki = rate[CYOKI]*frand();
	pa = rate[PA]*frand();

	if(gu > cyoki)
	{
		if(gu>pa) return GU;  /* gu大 */
		else return PA;  /* pa大 */
	}
	else
	{
		if(cyoki>pa) return CYOKI;  /* cyoki大 */
		else return PA;  /* pa大 */
	}

有了出拳类型,接下来就是判断输赢胜负了,代码如下:

	gain = payoffmatrix[myhand][ohand];  	/* 胜负判断 */

根据胜负去不断调整模型出拳比率,也就是数组rate。

	rate[myhand] += gain*ALPHA*rate[myhand];  	/* 学习出拳比例 */

判断输赢的矩阵如下:

	int payoffmatrix[3][3] = {{DRAW, WIN, LOSE},   	/* 胜负矩阵 */
							{LOSE, DRAW, WIN},
							{WIN, LOSE, DRAW}};

payoffmatrix[][] 数组中,分别用我方出拳mahand和对手出拳ohand赋值,就可以得到胜负结果。例如 出拳为 “石头”,即 0

出拳为“剪刀” ,即 “1”,那么,

payoffmatrix[GU][CYOKI] —— payoffmatrix[0][1] ——WIN。

下面是我一直输入 “0”, 也就是我一直出石头,的程序输出结果,

可以看到,在我一直出石头的局面下, 石头比率一直等于 1, 剪刀比率不断减少,布的比率不断增大。

  

上面的例子虽然简单,但可以帮助我们更好地理解机器学习的原理和方法。

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值