⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classify.cpp

📁 分类器的设计
💻 CPP
字号:
#include <windows.h>
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>


double pi=3.1415926;
//male=0;female=1
double train[20][4]={{4272.0,888,52,0},{33037,106997,35,0},
{46960,191298,74,1},{5139,224,40,1},{9576,10466,34,0},
{19619	,37571	,31	,1},{29825,4700,51,1},{6565,3542,39,0},
{23909,41540,43,0},{39350,11878,70,1},{20468,21740,58,0},
{7949,4562,26,0},{4018,964,22,0},{4054,8550,23,0},
{41877,21642,51,1},{943,138,27,0},{53095,30968,67,1},
{4118,3098,25,1},{3606,2528,30,0},{61620,7823,53,0}
};
double target[4]={23000,500,39,1};//蓝色叉所表示的位置即是
double maxium[4]={70000.0,210000,100,2};//各项最大值
//int credible[20]={0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,1,0,0,1};//分类,1表示可信,且用绿色;0表示不可信,且用红色表示(此为线性分类)
int credible[20]={1,0,1,0,1,0,1,0,0,0,1,1,1,0,1,0,0,0,1,0};//分类,1表示可信,且用绿色;0表示不可信,且用红色表示
int axisX=0,axisY=1;//表示参与训练的标准

char romania;
//K_NN方法
int k=6;

//以下为BP算法初始化
const int floor1=2;//中间层数
int level[floor1+2];//记录每层节点数
double weight[floor1+1][10][10];//每层节点不超过10个,此矩阵记录权重
double b[floor1+1][10];//记录偏移量
double n[floor1+1][10];//求和变量
double a[floor1+2][10];//每层输入量,即上一层输出量,因初始为原数据输入,故层数多1
double s[floor1+1][10];//反向传播时的中间量
double t[10];//输出终端
double e[10];//最终误差
double alfar=0.01;//学习率



void circlepoint(GLdouble x,GLdouble y,GLdouble radius)//画圆子程序
{
	double step=2.0*pi/25.0;
	for(int i=0;i<100;i++)
	{
		glVertex3d(x+radius*cos(i*step)*768/1024.0,y+radius*sin(i*step),0);
	}
}
double distance(double x,double y,double xx,double yy)
{
	return sqrt(pow(x-xx,2.0)+pow(y-yy,2.0));
}

double Gray(double x,double y)//计算每个点应属的颜色
{
	double distance1[20];
	double yangben[20][2];//转化为0-1坐标
	int cre[20];//用以存储类别
	double tran1;//用以作交换
	int tran2;//用以作交换
	int s=0;
	for(int i=0;i<20;i++)
	{
		yangben[i][0]=train[i][axisX]/maxium[axisX];
		yangben[i][1]=train[i][axisY]/maxium[axisY];
		cre[i]=credible[i];
		distance1[i]=distance(x,y,yangben[i][0],yangben[i][1]);
	}//计算点到各样本点距离
	for(int i=0;i<k;i++)
	{
		for(int j=i+1;j<20;j++)
		{
			if(distance1[i]>distance1[j])
			{
				tran1=distance1[i];distance1[i]=distance1[j];distance1[j]=tran1;
				tran2=cre[i];cre[i]=cre[j];cre[j]=tran2;
			}
		}
	}
	for(int i=0;i<k;i++)
		s=s+cre[i];
	if(s>k/2)
		return 1.0;
	else
		return 0.0;

}



double sigmoid(double x)
{
	return 1/(1+exp(-x));
}

double Dsigmoid(double x)
{
	return sigmoid(x)*(1-sigmoid(x));
}
void initBP(void)
{
//BP初始化
	level[0]=2;//输入端2个节点
	level[floor1+1]=1;//输出端1个节点
	for(int i=0;i<floor1;i++)
		level[i+1]=9;//设置中间层节点数均为3
	printf("%d %d %d\n",level[0],level[1],level[2]);
	for(int i=0;i<floor1+2-1;i++)//初始化权重矩阵及偏移量,共计 总层数-1 个
	{	
		for(int j=0;j<level[i+1];j++)
			b[i][j]=(rand()%100*0.01)-0.5;//初始化偏移量,[-0.5,0.5]

		for(int j=0;j<level[i+1];j++)//初始化权重矩阵
		{
			for(int k=0;k<level[i];k++)
			{
				weight[i][j][k]=(rand()%100*0.02)-1.0;//[-1,1]
			}
		}
	}
			
}

void computeBP(double x,double y,int z)//传入的x,y是原坐标
{
	//前向计算
	a[0][0]=x/maxium[axisX];a[0][1]=y/maxium[axisY];//初始化输入端
	t[0]=credible[z];//初始化输出终端
	
	for(int i=0;i<floor1+1;i++)//网格计算
	{
		for(int j=0;j<level[i+1];j++)
		{
			n[i][j]=0;
			for(int k=0;k<level[i];k++)
			{
				n[i][j]+=weight[i][j][k]*a[i][k];
			}
			n[i][j]+=b[i][j];
			
			
			a[i+1][j]=sigmoid(n[i][j]);//下一层输入
			
		}
		if(i==floor1)
			{
				
				for(int ii=0;ii<level[floor1+1];ii++)
					e[ii]=t[ii]-a[i][ii];//误差记录
			}
	}
	//反向传递过程
	//首先为各层敏感度s计算
	for(int ii=0;ii<level[floor1+1];ii++)
		s[floor1][ii]=-2*e[ii]*Dsigmoid(n[floor1][ii]);//最后一层s初始化
	for(int i=floor1-1;i>=0;i--)//反向计算s,i表示层数
	{
		for(int j=0;j<level[i+1];j++)//j表示本层节点
		{
			s[i][j]=0;
			for(int k=0;k<level[i+2];k++)//k表示上一层节点
			{
				s[i][j]+=s[i+1][k]*Dsigmoid(n[i][j])*weight[i+1][k][j];
			}
		}
	}//调整结束 

	for(int i=0;i<floor1+2-1;i++)//更改权重矩阵及偏移量,共计 总层数-1 个
	{	
		for(int j=0;j<level[i+1];j++)
			b[i][j]=b[i][j]-alfar*s[i][j];//更改偏移量,[-0.5,0.5]

		for(int j=0;j<level[i+1];j++)//更改权重矩阵
		{
			for(int k=0;k<level[i];k++)
			{
				weight[i][j][k]=weight[i][j][k]-alfar*s[i][j]*a[i][k];//[-1,1]
			}
		}
	}
	////输出	
	//for(int i=0;i<floor1+2-1;i++)//初始化权重矩阵及偏移量,共计 总层数-1 个
	//{	
	//	for(int j=0;j<level[i+1];j++)
	//		printf("b,	%f\n",b[i][j]);
	//	printf("\n");

	//	for(int j=0;j<level[i+1];j++)//初始化权重矩阵
	//	{
	//		for(int k=0;k<level[i];k++)
	//		{
	//			printf("weight,	%f\n",weight[i][j][k]);
	//		}
	//		printf("\n");
	//	}
	//}


}

double finalBP(double x,double y,int z)
{
	//前向计算
	double sum=0.0;//误差累加
	a[0][0]=x/maxium[axisX];a[0][1]=y/maxium[axisY];//初始化输入端
	t[0]=credible[z];//初始化输出终端
	
	for(int i=0;i<floor1+1;i++)//网格计算
	{
		for(int j=0;j<level[i+1];j++)
		{
			n[i][j]=0;
			for(int k=0;k<level[i];k++)
			{
				n[i][j]+=weight[i][j][k]*a[i][k];
			}
			n[i][j]+=b[i][j];
			
			
			a[i+1][j]=sigmoid(n[i][j]);//下一层输入
			
		}
						
	}
	for(int ii=0;ii<level[floor1+1];ii++)
	{
		e[ii]=t[ii]-a[floor1+1][ii];//误差记录
		sum+=pow(e[ii],2.0);
	}
	return sum;
			
}
double GrayBP(double x,double y)
{
	
	a[0][0]=x;a[0][1]=y;//初始化输入端
	
	for(int i=0;i<floor1+1;i++)//网格计算
	{
		for(int j=0;j<level[i+1];j++)
		{
			n[i][j]=0;
			for(int k=0;k<level[i];k++)
			{
				n[i][j]+=weight[i][j][k]*a[i][k];
			}
			n[i][j]+=b[i][j];
			
			
			a[i+1][j]=sigmoid(n[i][j]);//下一层输入
			
		}
						
	}
	//printf("%f\n",a[floor1+1][0]);
	if(a[floor1+1][0]>0.5)
		return 1.0;
	else
		return 0.0;
}
void CircleBP(void)
{
	double Esum=30.0;
	int Isum=0;

	while(Esum>0.1 && Isum<300000)
	{	
		//printf("%f	%d\n",Esum,Isum);

		Esum=0.0;
		Isum++;
		for(int i=0;i<20;i++)
			computeBP(train[i][axisX],train[i][axisY],i);
		
		for(int i=0;i<20;i++)
			Esum+=finalBP(train[i][axisX],train[i][axisY],i);
		Esum=Esum/20.0;
	}
	printf("%f	%d\n",Esum,Isum);

}

void display(void)
{
	glClearColor (1,1,1, 0.0);
	glClear (GL_COLOR_BUFFER_BIT);
	glColor3f (0,0.0,0.0);

	double red,green;
	
	
	
	
	//绘制背景
	if(romania=='k')
	{
		//K-NN
		printf("K的值为%d\n",k);
		glBegin(GL_POINTS);
		for(double u=-0.2;u<=1.0;u+=0.001)
		{
			for(double v=-0.2;v<=1.0;v+=0.001)
			{
				red=(1.0-Gray(u,v))*0.5;
				green=(Gray(u,v))*0.5;
				glColor3f(red+0.3,green+0.3,0+0.4);
				glVertex2d(u,v);
				
			}
		}
		glEnd();
	}
	

	////BP
	else if(romania=='b')
	{
		initBP();
		CircleBP();

		printf("隐层数目为%d,每层节点数为%d,激活函数为sigmoid函数\n",floor1,level[1]);
		glBegin(GL_POINTS);
		for(double u=-0.2;u<=1.0;u+=0.001)
		{
			for(double v=-0.2;v<=1.0;v+=0.001)
			{
				red=(1.0-GrayBP(u,v))*0.5;
				green=(GrayBP(u,v))*0.5;
				glColor3f(red+0.3,green+0.3,0+0.4);
				glVertex2d(u,v);
				
			}
		}
		glEnd();

	}
	//绘制输出样本点及坐标轴
		for(int i=0;i<20;i++)
		{
			if(credible[i]==0)
			{
				red=1.0;green=0.0;
			}
			else
			{
				red=0.0,green=1.0;
			}
			glColor3f(red,green,0.0);
			glBegin(GL_POLYGON);
				circlepoint(train[i][axisX]/maxium[axisX],train[i][axisY]/maxium[axisY],0.008);
			glEnd();
		}//初始化
	glColor3f(0,0,0);
	glBegin(GL_LINES);
		glVertex2d(-0.2,-0.2);
		glVertex2d(1,-0.2);
	glEnd();//坐标轴
	
	glBegin(GL_LINES);
		glVertex2d(-0.2,-0.2);
		glVertex2d(-0.2,1);
	glEnd();//坐标轴
	
	//下面绘制所需进行分类的目标点(十字叉)
	red=target[axisX]/maxium[axisX];
	green=target[axisY]/maxium[axisY];
	glColor3f(0,0,1);
	glBegin(GL_LINES);
		glVertex2d(red-0.008,green+0.008);
		glVertex2d(red+0.008,green-0.008);
	glEnd();//目标点
	
	glBegin(GL_LINES);
		glVertex2d(red-0.008,green-0.008);
		glVertex2d(red+0.008,green+0.008);
	glEnd();//目标点
	


	

	
	glFlush ();
}

void init (void)
{

glClearColor (0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-0.3, 1.1, -0.3, 1.1, -2.0, 100);//设置窗口
}

void mykey(unsigned char key,int x,int y)
{
	switch(key)
	{
	case 'k'://clear
		romania='k';
		glutPostRedisplay();
		break;
	

	case 'b':
		romania='b';
		glutPostRedisplay();
		break;
	
	default:
		break;

	}
}
void initInput(void)
{
	printf("   1		  2		 3		 4		   5\nIncome		Debts		Age		Sex		Credible\n\n");
	for(int i=0;i<20;i++)
	{
		if(train[i][3]<0.5)
		{
			printf("%f	%f	%f	male		%d\n",train[i][0],train[i][1],train[i][2],credible[i]);
		}
		else
		{
			printf("%f	%f	%f	female		%d\n",train[i][0],train[i][1],train[i][2],credible[i]);
		}
	}
	printf("\n\n请输入用以分类的两个标准(横纵坐标的属性)\n以1,2,3,4表示.例如:若以income为横轴,debts为纵轴,则输入1,2。\n");
	scanf("%d,%d",&axisX,&axisY);
	axisX--;axisY--;
	printf("\n键盘操作:‘k’表示调用K-NN算法,‘b’表示调用BP算法\n");
}
int main(int argc, char** argv)
{

initInput();
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize (1024, 768);
glutInitWindowPosition (100, 100);
glutCreateWindow ("classify");

init ();
glutDisplayFunc(display);
//glutMotionFunc(myMoveMouse);
glutKeyboardFunc(mykey);
//glutMouseFunc(myMouse);


glutMainLoop();
return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -