单个Rossenblat感知器的c语言实现

Rossenblat感知器可以被视为一种取定函数对应法则为某个限幅器的MCF神经元。若取硬限幅器阶跃函数step( )为对应法则,则Rossenblat感知器可表示为:

Y=step(\sum_{1}^{n}x_{i}\omega _{i}-\theta )

下面这段简易的c代码利用Rossenblat感知器实现了逻辑与运算,可以直接在Visual Studio上编译运行:

#define _CRT_SECURE_NO_WARNINGS

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

/* define Step Function */
float step(float x)
{
	float res;
	if(x>=0) res=1;
	else res=0;

	return res;
}

int main(void)
{
	float x1a,x2a,x1b,x2b,x1c,x2c,x1d,x2d; 
	float Yda,Ydb,Ydc,Ydd; 
	float Ya,Yb,Yc,Yd;
	float w1,w2;
	float a=0.01; /*初始化学习速率*/
	float ea,eb,ec,ed;  /*误差Yd-Y*/
	float x,y,res;
	int i=0,resR;
	float s=0.4;  /*初始化阈值θ*/

	/*逻辑或运算的真值表*/
	x1a=0;x2a=0;Yda=0;
	x1b=0;x2b=1;Ydb=1;
	x1c=1;x2c=0;Ydc=1;
	x1d=1;x2d=1;Ydd=1;

	w1=0.1;w2=0.1;  /*初始化权重*/

	Ya = 2; Yb = 2; Yc = 2; Yd = 2;  /*初始化神经元输出(仅为进入下面的循环)*/

	/*Training*/
	while(Yda!=Ya || Ydb!=Yb || Ydc!=Yc || Ydd!=Yd)
	{
		i=i+1;
		printf("iterations:%d\n",i);

		/* a training*/
		Ya=step(x1a*w1+x2a*w2-s);
		ea=Yda-Ya;
		if(ea!=0)
		{
			w1=w1+a*x1a*ea;
			w2=w2+a*x2a*ea;
		}
		printf("weight1:w1=%f,w2=%f;ea=%f\n",w1,w2,ea);

		/* b training*/
		Yb=step(x1b*w1+x2b*w2-s);
		eb=Ydb-Yb;
		if(eb!=0)
		{
			w1=w1+a*x1b*eb;
			w2=w2+a*x2b*eb;
		}
		printf("weight2:w1=%f,w2=%f;eb=%f\n",w1,w2,eb);

		/* c training*/
		Yc=step(x1c*w1+x2c*w2-s);
		ec=Ydc-Yc;
		if(ec!=0)
		{
			w1=w1+a*x1c*ec;
			w2=w2+a*x2c*ec;
		}
		printf("weight3:w1=%f,w2=%f;ec=%f\n",w1,w2,ec);


		/* d training*/
		Yd=step(x1d*w1+x2d*w2-s);
		ed=Ydd-Yd;
		if(ed!=0)
		{
			w1=w1+a*x1d*ed;
			w2=w2+a*x2d*ed;
		}
		printf("weight4:w1=%f,w2=%f;ed=%f\n",w1,w2,ed);
	
		printf("finished\n");
	}

	/*Test*/
	printf("training result:w1=%f,w2=%f\n",w1,w2);
	printf("Input:");
	scanf("%f %f", &x,&y);
	res=step(x*w1+y*w2-s);
	resR=res;
	printf("%d\n", resR);

	system("pause");

	return 0;
}

激活函数使用了阶跃函数step( )。

注意其中w1,w2,s,a初始化时都是可调的,但理论上这会影响训练的迭代次数。

该程序除定义阶跃函数step( )外可分为两部分,前半部分为训练,后半部分为测试。由于训练所需的数据已经写好,并通过while循环实现迭代,所以程序运行后神经元即可训练完毕。此后会出现Input,在其后输入测试值(0或1),就可以输出其对应的逻辑值。

单个Rossenblat感知器可以处理线性分割区域,所以但凡两组结果可以被划分到两个不同的决策区域里,都能用感知器实现。事实上,改变真值表,不但可以实现逻辑与运算,也可以实现逻辑非与运算,但这时候需要对阶跃函数和delta规则作相应的调整。其原因在于:神经元线性分割了一个二维平面,当不改变阶跃函数时,上方的决策区域取值为1,下方取值为0,为使之进行非与运算,需要将取值调换;同时,必须将delta规则中的加号变为减号,使之能使Yd与Y的差值不断缩小。

测试效果如下图所示(部分):

iterations后面为迭代次数。注意后面的ea、eb、ec、ed都是按照上一组w1和w2计算的,每行e左侧的权重都是本轮修正后的权重。当x1和x2四种情况误差均为0时训练结束,w1和w2分别收敛到0.41(两个权重未必收敛于同一值,这会受到权重初始值的影响)。Input后输入0 1,执行逻辑或运算,输出正确结果1。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张向南zhangxn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值