knn
//#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};//蓝色叉所表示的位置即是//Display position place immediately fork 蓝色 Shi
double maxium[4]={70000.0,210000,100,2};//各项最大值//Up 值 each clause
//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-nn %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]);
printf("The first act of %d,Acts of nodes %d, Acts super active function sigmoid Function\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");
printf("\n\nStandards need (next target attribute)\n Than 1,2,3,4 Display. Example For:Younger than income axis,debts axis,Enter 1,2。\n");
scanf("%d,%d",&axisX,&axisY);
axisX--;axisY--;
//printf("\n键盘操作:‘k’表示调用K-NN算法,‘b’表示调用BP算法\n");
printf("\nKeyboard Operation:‘k’ Show K-NN algorithm,‘b’ Show BP algorithm\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;
}