感知器算法及其实现

感知器算法及其实现

1.1 算法描述:

     感知器算法(Perception Approach)是通过对已知类别的训练样本集的学习,从而寻找到一个满足判别函数的权向量。对两类线性可分的模式类,具体步骤如下:

   (1)选择N个分别属于w1类和w2类的模式样本构成训练样本集,将训练样本写成增广向量形式,并对样本进行编              号和规范化处理。任取权向量初始值开始迭代。

   (2)用全部样本进行一轮迭代。每输入一个样本,计算一次判别函数的值,根据结果正误修正权向量,并将迭代                次数加1。权向量的校正分为以下两种情况进行:

          1.若判别函数的值小于等于0,说明分类器对样本的分类发生错误,需要校正权向量。

          2.若判别函数的值大于0,说明分类正确,权向量不变。

   (3)分析分类结果,只要在迭代中有样本分类发生错误,就继续进行下一轮迭代过程,直至全部样本都获得了正                确的分类结果,迭代结束。此时得到的权向量即为算法结果。 

1.2 算法实现

     算法实现效果如下图1所示。


图1 两类情况下的感知器算法的实现

1.3 代码如下:

本代码使用了OpenGL图形程序接口,需要使用glut库,具体使用方法请自行查找相关文档,此处不再介绍。

/*
感知器算法,分为两类
*/
#define N1  30
#define N2  40
#include <stdio.h>
#include <vector>
#include <time.h>
#include <GL/glut.h>

//模式结构体
struct Pattern
{
	int x1,x2;//x1,x2表示特征
	int c;//c代表添加的量
};
//定义w权向量
Pattern w;
//定义w1与w2数组
Pattern w1[N1],w2[N2];

void init()
{
	glClearColor(1.0f,1.0f,1.0f,1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
}
void display()
{
	float temp1,temp2;
	if(w.x2==0)
	{
		temp1 = (float)(-w.c)/(float)(w.x1);
		glColor3f(1.0f,0.0f,0.0f);
		glEnable(GL_POINT_SMOOTH);
		glBegin(GL_LINES);
		glVertex2f(temp1,-1);
		glVertex2f(temp1,20);
		glEnd();
		glFlush();
	}
	else
	{
		temp1 = (float)(-w.c+2*w.x1)/(float)(w.x2);
		temp2 = (float)(-w.c-20*w.x1)/(float)(w.x2);

		glColor3f(1.0f,0.0f,0.0f);
		glEnable(GL_POINT_SMOOTH);
		glBegin(GL_LINES);
		glVertex2f(-2,temp1);
		glVertex2f(20,temp2);
		glEnd();
		glFlush();
	}
	glPointSize(5.0);
	glBegin(GL_POINTS);
	int i,j;
	for(i = 0;i < N1; i++)
	{
		glColor3f(1.0,0.0,0.0);
		glVertex2f(w1[i].x1,w1[i].x2);
	}
	for(j = 0;j < N2; j++)
	{
		glColor3f(0.0,0.0,1.0);
		glVertex2f(w2[j].x1,w2[j].x2);
	}
	glEnd();
	glFlush();
}
int main(int argc,char *argv[])
{
	int i,j,count = 0;
	w.x1 = 1;
	w.x2 = 1;
	w.c = 1;
	//产生随机数的种子
	printf("这是第一类中的点\n");
	srand((unsigned)time(NULL));
	for (i = 0; i < N1; i++)
	{
		w1[i].x1=rand()%10;
		w1[i].x2=rand()%10;
		w1[i].c=1;
		//打印随机产生的点
		printf("%d %d\n",w1[i].x1,w1[i].x2);
	}
	printf("这是第二类中的点\n");
	srand((unsigned)time(NULL));
	for (j = 0; j < N2; j++)
	{
		w2[j].x1=10+rand()%10;
		w2[j].x2=10+rand()%10;
		w2[j].c=1;
		//打印随机产生的点
		printf("%d %d\n",w2[j].x1,w2[j].x2);
	}
	//感知器迭代判断
	while(1)
	{
		for (i = 0;i < N1; i++)
		{
			if(count>=N1+N2) break;
			if(((w1[i].x1*w.x1)+(w1[i].x2*w.x2)+(w1[i].c*w.c))>0)
				count++;
			else
			{
				count=0;
				w.x1=w.x1+w1[i].x1;
				w.x2=w.x2+w1[i].x2;
				w.c=w.c+w1[i].c;
			}
		}
		for (j = 0;j < N2; j++)
		{
			if(count>=N1+N2) break;
			if(((w2[j].x1*w.x1)+(w2[j].x2*w.x2)+(w2[j].c*w.c))<0)
				count++;
			else
			{
				count=0;
				w.x1=w.x1-w2[j].x1;
				w.x2=w.x2-w2[j].x2;
				w.c=w.c-w2[j].c;
			}
		}
		if(count==N1+N2) break;
	}
	printf("线性分类器的权矢量的值");
	printf("%2d,%2d,%2d\n",w.x1,w.x2,w.c);

	glutInit(&argc,argv);//初始化glut
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);//设置显示属性为RGB颜色,单缓冲
	glutInitWindowSize(300,300);//设置窗口大小
	glutInitWindowPosition(200,100);//设置窗口位置
	glutCreateWindow("感知器算法的设计");//生成窗口
	init();
	gluOrtho2D(-1,20,-1,20);
	glutDisplayFunc(&display);//显示回调
	glutMainLoop();
	system("pause");

	return 0;
}


1. 感知器算法 感知器算法是通过训练模式的迭代和学习算法,产生线性可分的模式判别函数。感知器算法就是通过对训练模式样本集的“学习”得出判别函数的系数解。在本次实验中,我们主要是采用硬限幅函数进行分类。 感知器的训练算法如下: 设输入矢量 , 加权矢量 ,则神经元 的输出可通过下式来计算 (1) 这里对于训练结束我们判断的依据是实际输出值与理想预期值之间误差的均方值最小。定义 它的均方值记作 ,令 , 则可以推出 (2) 可证存在最佳的加权矢量 ,使 达到最小。解得 (3) 式(3)给出了求最佳加权矢量的方法,但是需要做大量的统计计算,并且需要解决高阶矩阵求逆的问题,这些都是非常困难的。于是我们给出一种递推求解的方法: 在给定初始权值后,以这种方法可以得到递推公式: (4) 用这种方法虽然可以保证求得严格的最佳解,且避开了矩阵求逆的困难,但学习过程中的每一步仍需完成大量的统计计算。 2.BP算法 由于硬限幅函数是非可微函数,不能实现多层神经网络的一种有效的LMS学习算法。而BP算法中所用到的是Sigmoid型函数,它既具有完成分类所需的非线性特性,又具有实现LMS算法所需的可微特性。采用S型函数的神经元的输入和输出之间的关系为: (5) 采用了S型函数就可将用于单神经元的LMS学习算法适当推广,得到一种适用于前向多层神经网络的有效学习算法。 我们现在研究一个采用S型函数的前向三层神经网络来说明其原理。 对于训练样本p,它的输入是N维矢量X,X= ,网络的第一,二,三层分别包括J,K,M个神经元,它的总输出是一个M维矢量,Y= ,第i层到第i+1层之间的权重系数用 来表示。可设前向三层神经网络输出各个分量的理想值是 ,i=0,1,……M-1,而这些分量的实际值是 , i=0,1,……M-1,理想值和实际值之间的误差是 。各输出误差的平方和可以表示为: (6) 现在我们希望改变网络中的各个加权系数 ,使得 尽可能的减小。为此我们可以采取最陡下降算法的公式来调整权重系数 。公式如下: 式中的 是学习的步幅,它应随学习过程而变化。 对于通用神经层,它的各个输出 与各个输入 之间的关系可以表示为: 如果设 ,则 式中的 表示s型函数。我们不难看出上式即为给输入加一个恒等于1的部分,在神经网络中也应相应的加一个节点,而且这个节点的权系数就是这一层网络的阈值。经推倒可得权系数调整的递推公式如下: (7) 对输出层: 对隐含层: 现对于三层神经网络有 l=3时(输出层) l=2时(隐含层) l=1时(第一层) 其中: 可见,这一算法的计算过程是先计算第三层(即输出层)的各项“误差分量” ,然 后用 计算第二层(隐含层)的“等效误差分量” ,最后再用 计算第一层(隐含层)的“等效误差分量”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值