K最临近分类算法Word文档格式.docx
《K最临近分类算法Word文档格式.docx》由会员分享,可在线阅读,更多相关《K最临近分类算法Word文档格式.docx(28页珍藏版)》请在冰豆网上搜索。
![K最临近分类算法Word文档格式.docx](https://file1.bdocx.com/fileroot1/2023-1/21/3d3fcb78-6d78-45d6-af19-6133d46b4fac/3d3fcb78-6d78-45d6-af19-6133d46b4fac1.gif)
KNN(kNearestNeighbors)算法又叫k最临近方法,假设每一个类包含多个样本数据,而且每个数据都有一个唯一的类标记表示这些样本是属于哪一个分类,KNN就是计算每个样本数据到待分类数据的距离,如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
KNN方法虽然从原理上也依赖于极限定理,但在类别决策时,只与极少量的相邻样本有关。
因此,采用这种方法可以较好地避免样本的不平衡问题。
另外,由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
该方法的不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。
目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。
该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分。
(1)算法思路:
K-最临近分类方法存放所有的训练样本,在接受待分类的新样本之前不需构造模型,并且直到新的(未标记的)样本需要分类时才建立分类。
K-最临近分类基于类比学习,其训练样本由N维数值属性描述,每个样本代表N维空间的一个点。
这样,所有训练样本都存放在N维模式空间中。
给定一个未知样本,k-最临近分类法搜索模式空间,找出最接近未知样本的K个训练样本。
这K个训练样本是未知样本的K个“近邻”。
“临近性”又称为相异度(Dissimilarity),由欧几里德距离定义,其中两个点X(x1,x2,…xn)和Y(y1,y2,…yn)的欧几里德距离是:
未知样本被分配到K个最临近者中最公共的类。
在最简单的情况下,也就是当K=1时,未知样本被指定到模式空间中与之最临近的训练样本的类。
(2)算法步骤:
step.1---初始化距离为最大值
step.2---计算未知样本和每个训练样本的距离dist
step.3---得到目前K个最临近样本中的最大距离maxdist
step.4---如果dist小于maxdist,则将该训练样本作为K-最近邻样本
step.5---重复步骤2、3、4,直到未知样本和所有训练样本的距离都算完
step.6---统计K-最近邻样本中每个类标号出现的次数
step.7---选择出现频率最大的类标号作为未知样本的类标号
三、算法源代码
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
//KNN.cppK-最近邻分类算法
#include<
stdlib.h>
stdio.h>
memory.h>
string.h>
iostream.h>
math.h>
fstream.h>
//宏定义
#defineATTR_NUM4//属性数目
#defineMAX_SIZE_OF_TRAINING_SET1000//训练数据集的最大大小
#defineMAX_SIZE_OF_TEST_SET100//测试数据集的最大大小
#defineMAX_VALUE10000.0//属性最大值
#defineK7
//结构体
structdataVector{
intID;
//ID号
charclassLabel[15];
//分类标号
doubleattributes[ATTR_NUM];
//属性
};
structdistanceStruct{
doubledistance;
//距离
//全局变量
structdataVectorgTrainingSet[MAX_SIZE_OF_TRAINING_SET];
//训练数据集
structdataVectorgTestSet[MAX_SIZE_OF_TEST_SET];
//测试数据集
structdistanceStructgNearestDistance[K];
//K个最近邻距离
intcurTrainingSetSize=0;
//训练数据集的大小
intcurTestSetSize=0;
//测试数据集的大小
//求vector1=(x1,x2,...,xn)和vector2=(y1,y2,...,yn)的欧几里德距离
doubleDistance(structdataVectorvector1,structdataVectorvector2)
{
doubledist,sum=0.0;
for(inti=0;
i<
ATTR_NUM;
i++)
{
sum+=(vector1.attributes[i]-vector2.attributes[i])*(vector1.attributes[i]-vector2.attributes[i]);
}
dist=sqrt(sum);
returndist;
}
//得到gNearestDistance中的最大距离,返回下标
intGetMaxDistance()
intmaxNo=0;
for(inti=1;
K;
if(gNearestDistance[i].distance>
gNearestDistance[maxNo].distance)maxNo=i;
returnmaxNo;
//对未知样本Sample分类
char*Classify(structdataVectorSample)
doubledist=0;
intmaxid=0,freq[K],i,tmpfreq=1;
;
char*curClassLable=gNearestDistance[0].classLabel;
memset(freq,1,sizeof(freq));
//step.1---初始化距离为最大值
for(i=0;
gNearestDistance[i].distance=MAX_VALUE;
//step.2---计算K-最近邻距离
curTrainingSetSize;
//step.2.1---计算未知样本和每个训练样本的距离
dist=Distance(gTrainingSet[i],Sample);
//step.2.2---得到gNearestDistance中的最大距离
maxid=GetMaxDistance();
//step.2.3---如果距离小于gNearestDistance中的最大距离,则将该样本作为K-最近邻样本
if(dist<
gNearestDistance[maxid].distance)
{
gNearestDistance[maxid].ID=gTrainingSet[i].ID;
gNearestDistance[maxid].distance=dist;
strcpy(gNearestDistance[maxid].classLabel,gTrainingSet[i].classLabel);
}
//step.3---统计每个类出现的次数
i++)
for(intj=0;
j<
j++)
if((i!
=j)&
&
(strcmp(gNearestDistance[i].classLabel,gNearestDistance[j].classLabel)==0))
{
freq[i]+=1;
}
//step.4---选择出现频率最大的类标号
if(freq[i]>
tmpfreq)
tmpfreq=freq[i];
curClassLable=gNearestDistance[i].classLabel;
returncurClassLable;
//主函数
voidmain()
{
charc;
char*classLabel="
"
inti,j,rowNo=0,TruePositive=0,FalsePositive=0;
ifstreamfilein("
iris.data"
);
FILE*fp;
if(filein.fail()){cout<
<
Can'
topendata.txt"
endl;
return;
//step.1---读文件
while(!
filein.eof())
rowNo++;
//第一组数据rowNo=1
if(curTrainingSetSize>
=MAX_SIZE_OF_TRAINING_SET)
cout<
Thetrainingsethas"
MAX_SIZE_OF_TRAINING_SET<
examples!
endl<
break;
}
//rowNo%3!
=0的100组数据作为训练数据集
if(rowNo%3!
=0)
{
gTrainingSet[curTrainingSetSize].ID=rowNo;
for(inti=0;
i<
ATTR_NUM;
{
filein>
>
gTrainingSet[curTrainingSetSize].attributes[i];
c;
}
filein>
gTrainingSet[curTrainingSetSize].classLabel;
curTrainingSetSize++;
//剩下rowNo%3==0的50组做测试数据集
elseif(rowNo%3==0)
gTestSet[curTestSetSize].ID=rowNo;
{
gTestSet[curTestSetSize].attributes[i];
}
gTestSet[curTestSetSize].classLabel;
curTestSetSize++;
filein.close();
//step.2---KNN算法进行分类,并将结果写到文件iris_OutPut.txt
fp=fopen("
iris_OutPut.txt"
"
w+t"
//用KNN算法进行分类
fprintf(fp,"
************************************程序说明***************************************\n"
**采用KNN算法对iris.data分类。
为了操作方便,对各组数据添加rowNo属性,第一组rowNo=1!
\n"
**共有150组数据,选择rowNo模3不等于0的100组作为训练数据集,剩下的50组做测试数据集\n"
***********************************************************************************\n\n"
************************************实验结果***************************************\n\n"
curTestSetSize;
************************************第%d组数据**************************************\n"
i+1);
classLabel=Classify(gTestSet[i]);
if(strcmp(classLabel,gTestSet[i].classLabel)==0)//相等时,分类正确
TruePositive++;
cout<
rowNo:
"
gTestSet[i].ID<
\t"
KNN分类结果:
classLabel<
(正确类标号:
gTestSet[i].classLabel<
)\n"
fprintf(fp,"
%3d\tKNN分类结果:
%s(正确类标号:
%s)\n"
gTestSet[i].ID,classLabel,gTestSet[i].classLabel);
if(strcmp(classLabel,gTestSet[i].classLabel)!
=0)//不等时,分类错误
//cout<
***分类错误***\n"
fprintf(fp,"
%d-最临近数据:
K);
for(j=0;
gNearestDistance[j].ID<
\t"
gNearestDistance[j].distance<
gNearestDistance[j].classLabel[15]<
%3d\tDistance:
%f\tClassLable:
%s\n"
gNearestDistance[j].ID,gNearestDistance[j].distance,gNearestDistance[j].classLabel);
FalsePositive=curTestSetSize-TruePositive;
***********************************结果分析**************************************\n"
i);
TP(Truepositive):
%d\nFP(Falsepositive):
%d\naccuracy:
%f\n"
TruePositive,FalsePositive,double(TruePositive)/(curTestSetSize-1));
fclose(fp);
四、详细描述该算法获得的模型
采用第二包数据IrisDataSet,共有150组数据,考虑到训练数据集的随机性和多样性,选择rowNo模3不等于0的100组作为训练数据集,剩下的50组做测试数据集。
对未知样本进行分类(括号里的正确类标号是读取的iris.data文件里的类标号,括号外的是计算所得),本文取k=7个最邻近数据。
以第19组为例进行说明,未知样本ROWNO为57,经过KNN算法分类,与之最临近的7组数据rowNo号分别为:
52、86、128、139、92、64、71,其中类标号为Iris-versicolor的有5个,类标号为Iris-virginica的有2个,Iris-versicolor为最多,因此据此估计该组样本的类标号为Iris-versicolor。
50组测试样本运行结果如下:
************************************程序说明***************************************
**共有150组数据,选择rowNo模3不等于0的100组作为训练数据集,剩下的50组做测试数据集
***********************************************************************************
************************************实验结果***************************************
************************************第1组数据**************************************
3KNN分类结果:
Iris-setosa(正确类标号:
Iris-setosa)
7-最临近数据:
43Distance:
0.300000ClassLable:
Iris-setosa
2Distance:
4Distance:
0.244949ClassLable:
13Distance:
0.264575ClassLable:
7Distance:
46Distance:
10Distance:
0.316228ClassLable:
Iris