forked from myazi/myLearn
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkNN.cpp
195 lines (173 loc) · 4.77 KB
/
kNN.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <math.h>
#include "matrix.h"
using namespace std;
/***数据归一化处理,data[i][j]-min[j]/range[j]**/
int autoNorm(Matrix x)
{
int j=0,i=0;
Matrix minVals;
minVals.initMatrix(&minVals,1,x.row,MAX);
Matrix maxVals;
maxVals.initMatrix(&maxVals,1,x.row,MIN);
Matrix ranges;
ranges.initMatrix(&ranges,1,x.row);
for(j=0; j<x.row; j++)
{
minVals.mat[0][j]=x.mat[0][j];
maxVals.mat[0][j]=minVals.mat[0][j];
}
for(i=0; i<x.col; i++)
{
for(j=0; j<x.row; j++)
{
if(x.mat[i][j]<minVals.mat[0][j])
minVals.mat[0][j]=x.mat[i][j];
if(x.mat[i][j]>maxVals.mat[0][j])
maxVals.mat[0][j]=x.mat[i][j];
}
}
for(i=0; i<x.row; i++)
ranges.mat[0][i]=maxVals.mat[0][i]-minVals.mat[0][i];
for(i=0; i<x.col; i++)
{
for(j=0; j<x.row; j++)
{
x.mat[i][j]-=minVals.mat[0][j];
x.mat[i][j]/=ranges.mat[0][j];
//cout<<x.mat[i][j]<<" ";
}
//cout<<endl;
}
return 0;
}
/**计算每个测试样本与训练样本的距离,保存在distance矩阵中**/
Matrix cdistances(Matrix test,Matrix x)
{
int i,j;
Matrix distances;
distances.initMatrix(&distances,x.col,1,0);
for(i=0; i<x.col; i++)
{
for(j=0; j<x.row; j++)
{
distances.mat[i][0]+=pow((x.mat[i][j]-test.mat[0][j]),2);
}
distances.mat[i][0]=sqrt(distances.mat[i][0]);
//cout<<"dis="<<distances.mat[i][0]<<endl;
}
return distances;
}
/***选择出K个近邻**/
Matrix getK(Matrix oneTest,Matrix x,int K)
{
int i,j,k;
//为每一个测试样本初始化k个近邻为前k个训练样本,并记录近邻的id
Matrix distances;
distances.initMatrix(&distances,x.col,1);
distances=cdistances(oneTest,x);
Matrix Kdistances;
Kdistances.initMatrix(&Kdistances,K,2);
double Max=-1;
int Maxi=-1;
for(i=0; i<K; i++)
{
Kdistances.mat[i][0]=distances.mat[i][0];
Kdistances.mat[i][1]=i;//记录近邻的id
if(Kdistances.mat[i][0]>Max)
{
Max=Kdistances.mat[i][0];
Maxi=i;//选出当前k个近邻中最大的一个
}
}
//为每一个测试样本从第K个训练样本中遍历更新新的k个近邻
for(i=K; i<x.col; i++)
{
if(distances.mat[i][0]<Max)
{
Kdistances.mat[Maxi][0]=distances.mat[i][0];
Max=distances.mat[i][0];//暂时更新当前替换的距离为最大距离,因为已经不能用之前的最大距离了
Kdistances.mat[Maxi][1]=i;//记录近邻的id
for(k=0; k<K; k++)
{
if(Kdistances.mat[k][0]>Max)
{
Max=Kdistances.mat[k][0];
Maxi=k;//选出当前k个近邻中最大的一个
}
}
}
}
return Kdistances;
}
//KNN决规则,这里采用平局权重投票,且不考虑样本不均衡问题
/**
1,knn分类决策函数,首先对训练数据和测试数据进行归一化,
2,计算每一个测试样本到m个训练样本的距离
3,从m个距离中选出最小的k个距离,并记录这k个最小距离的样本
4,由k个样本加权投票得到最终的决策类别
***/
int classfiy(Matrix testData,Matrix testDatay,Matrix x,Matrix y,int K)
{
int i,j,k;
int sumz=0,sumf=0;
Matrix knn;
knn.initMatrix(&knn,K,2);
autoNorm(x);
autoNorm(testData);
for(i=0; i<testData.col; i++)
{
sumz=0;
sumf=0;
Matrix oneTest;
oneTest.initMatrix(&oneTest,1,x.row);
oneTest=oneTest.getOneCol(testData,i);
knn=getK(oneTest,x,10);
for(j=0; j<K; j++)
{
if(y.mat[int(knn.mat[j][1])][0]==1)
sumz++;
else
sumf++;
cout<<y.mat[int(knn.mat[j][1])][0]<<" ";
}
if(sumz>sumf)
cout<<"juece="<<"1"<<"&"<<"shiji="<<testDatay.mat[i][0]<<endl;
else
cout<<"juece="<<"-1"<<"&"<<"shiji="<<testDatay.mat[i][0]<<endl;
}
return 0;
}
int main()
{
dataToMatrix dtm;
cout<<"loadData"<<endl;
cout<<"----------------------"<<endl;
char file[20]="data\\knn.txt";
dtm.loadData(&dtm,file);
//dtm.print(dtm);
Matrix x;
x.loadMatrix(&x,dtm);
Matrix y;
y.initMatrix(&y,x.col,1);
y=y.getOneRow(x,x.row);
x.deleteOneRow(&x,x.row);
dataToMatrix dtmTest;
cout<<"loadData"<<endl;
cout<<"----------------------"<<endl;
char testFile[20]="data\\knnTest.txt";
dtmTest.loadData(&dtmTest,testFile);
//dtmTest.print(dtmTest);
Matrix testData;
testData.loadMatrix(&testData,dtmTest);
Matrix testDatay;
testDatay.initMatrix(&testDatay,x.col,1);
testDatay=testDatay.getOneRow(testData,testData.row);
testData.deleteOneRow(&testData,testData.row);
classfiy(testData,testDatay,x,y,10);
return 0;
}