Kmeans实验报告文档格式.docx
- 文档编号:18143371
- 上传时间:2022-12-13
- 格式:DOCX
- 页数:18
- 大小:24.63KB
Kmeans实验报告文档格式.docx
《Kmeans实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《Kmeans实验报告文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
满足方差最小标准的k个聚类
3.需求分析
K-Mean是一种分割式分群方法,其主要目标是要在大量高纬的资料点中找出具有代表性的资料点;
这些资料点可以称为群中心,代表点;
然后再根据这些群中心,进行后续的处理,这些处理可以包含
1)资料压缩:
以少数的资料点来代表大量的资料,达到资料压缩的功能;
2)资料分类:
以少数代表点来代表特点类别的资料,可以降低资料量及计算量;
分割式分群法的目的是希望尽量減小每个群聚中,每一点与群中心的距离平方差(squareerror)。
假設我们現在有一組包含c个群聚的資料,其中第k个群聚可以用集合Gk來表示,假设Gk包含nk个資料{x1,x2,…,xnk),此群聚中心为yk,则该群聚的平方差ek可以定义为:
ek=Si|xi-yk|2,其中xi是属于第k群的资料点。
而这c个群聚的总和平方差E便是每个群聚的平方差总和:
E=Sk=1~cek
我们分群的方法,就改成是一个最佳化的問題,換句话說,我們要如何选取c个群聚以及相关的群中心,使得E的值为最小。
4.详细设计
k-means算法是一种基于样本间相似性度量的间接聚类方法,属于非监督学习方法。
此算法以k为参数,把n个对象分为k个簇,以使簇内具有较高的相似度,而且簇间的相似度较低。
相似度的计算根据一个簇中对象的平均值(被看作簇的重心)来进行。
此算法首先随机选择k个对象,每个对象代表一个聚类的质心。
对于其余的每一个对象,根据该对象与各聚类质心之间的距离,把它分配到与之最相似的聚类中。
然后,计算每个聚类的新质心。
重复上述过程,直到准则函数会聚。
k-means算法是一种较典型的逐点修改迭代的动态聚类算法,其要点是以误差平方和为准则函数。
逐点修改类中心:
一个象元样本按某一原则,归属于某一组类后,就要重新计算这个组类的均值,并且以新的均值作为凝聚中心点进行下一次象元素聚类;
逐批修改类中心:
在全部象元样本按某一组的类中心分类之后,再计算修改各类的均值,作为下一次分类的凝聚中心点。
k-means算法接受输入量k;
然后将n个数据对象划分为k个聚类以便使得所获得的聚类满足:
同一聚类中的对象相似度较高;
而不同聚类中的对象相似度较小。
聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。
k-means算法把N个点聚集成K个组合的算法,要求任意输入K各对象作为初始中心点,这个的最大疑问就是怎么能够通过这随便选择的K个点来达到满足要求的K个组合呢。
K-means算法其实每次迭代都会改变中心,也就是初始的K各对象作为中心点在每一次迭代后都会更新。
首先以这K各顶点作为初始K个聚类的中心顶点,第一轮计算所有的其他顶点与这个K个顶点的相似度,取相似度最大的或者说与这K个顶点中某个顶点距离最近的顶点加入这个顶点所代表的cluster中,注意在第一轮检测所有顶点的距离并判断其属于哪个簇的过程中,这K各簇的中心仍然是以这K个顶点作为代表的。
第一轮计算完毕之后,相当于形成了以这K个顶点为中心的K个聚类,此时计算这K个聚类的聚集度,即各个顶点与其中心顶点的距离和作为考察条件,在进行下一轮的迭代的时候,中心顶点就变了,此时就变成第一轮生成的K个聚类的中心顶点作为新的中心顶点并按照第一轮迭代的方法进行重新聚类,并计算各个聚类的聚合度,当聚合度不变的时候或者定义了最大迭代次数的时候,算法表示运算完毕。
5.测试及运行结果
0.49,0.29,0.48,0.5,0.56,0.24,0.35
0.07,0.4,0.48,0.5,0.54,0.35,0.44
0.56,0.4,0.48,0.5,0.49,0.37,0.46
0.59,0.49,0.48,0.5,0.52,0.45,0.36
0.23,0.32,0.48,0.5,0.55,0.25,0.35
0.67,0.39,0.48,0.5,0.36,0.38,0.46
0.29,0.28,0.48,0.5,0.44,0.23,0.34
0.21,0.34,0.48,0.5,0.51,0.28,0.39
重复聚类次数:
10
分类正确率:
78.27381%
选择的下标如下:
19180213220230236266329
分类结果列表:
2
6
6.程序源码及注释
/**
*K-Means聚类的主程序类
**/
publicclassK_Means{
publicK_Means(){
//TODO自动生成构造函数存根
clusterList=newClusterSet();
dataSet=newMatrix();
classData=newArrayList<
Integer>
();
}
staticdoublesquareDistance(PointNDp1,PointNDp2)
{
if(p1.dimension==p2.dimension)
{
doubledistance=0.0;
for(inti=0;
i<
p1.dimension;
i++)
{
doublep1p=p1.pointND.get(i);
doublep2p=p2.pointND.get(i);
distance+=Math.pow((p1p-p2p),2);
}
returndistance;
}
return-1.0;
/**
*从外部数据文件中构造Matrix数据集
*@paramdataFile外部数据文件,文件中的每一行中数据间使用逗号分隔
*@returnMatrix对象数据集
*@throwsIOException
*/
privateMatrixbuildMatrix(FiledataFile)throwsIOException
Matrixmatrix=newMatrix();
ArrayList<
DataItem>
rows=matrix.rows;
FileInputStreamfin=newFileInputStream(dataFile);
BufferedReaderreader=newBufferedReader(newInputStreamReader(fin));
Stringline=reader.readLine();
String[]items=line.split("
"
);
matrix.setWidth(items.length);
//读取文件中的每一行
while(line!
=null)
{
items=line.split("
"
DataItemrow=newDataItem();
PointNDp=row.rowdata;
//每一行为一个N维坐标点
ArrayList<
Double>
points=p.pointND;
//将每个数据转为浮点型
items.length;
points.add(Double.parseDouble(items[i]));
rows.add(row);
line=reader.readLine();
matrix.setHeight();
reader.close();
returnmatrix;
*由Matrix数据集对象初始化簇类列表
*使用随机选择的方法
*@paramtheDataSetMatrix数据集
*@paramnum簇类数目
*@return
privateClusterSetinitClusterSet(MatrixtheDataSet,intnum)
returnrandomInit(theDataSet,num);
//returnthis.bestInit(dataSet,num);
*随机选择k个数据项,作为k个簇类的中心
*@paramtheDataSetMatrix数据集对象
*@paramnum簇类个数
*@return簇类列表
privateClusterSetrandomInit(MatrixtheDataSet,intnum)
//哈希集,记录生成的下标
HashSet<
ht=newHashSet<
ClusterSetnewClusterList=newClusterSet();
intrange=theDataSet.height;
rows=theDataSet.rows;
//System.out.println("
随机选择"
+num+"
个数据项构造簇集..."
//随机选择法
intindex=(int)(range*Math.random());
ht.add(index);
//生成num个簇类
for(inti=0;
num;
index=(int)(range*Math.random());
//保证不会生成两个相同的下标
while(ht.contains(index))
index=(int)(range*Math.random());
goodIndexes[i]=index;
ht.add(index);
//intindex=i;
//System.out.print(index+"
DataItemrow=rows.get(index);
PointNDcenter=row.rowdata;
Clusterclus=newCluster(center);
newClusterList.clusterList.add(clus);
newClusterList.setCount();
returnnewClusterList;
*对数组进行简单的插入排序
*@paramarray
privateint[]sortArray(int[]array)
for(inti=1;
array.length;
inttmp=array[i];
intj=i;
for(;
j>
0&
&
tmp<
array[j-1];
j--)
array[j]=array[j-1];
array[j]=tmp;
returnarray;
*聚类过程
*@paramclusterList簇集列表
*@paramtheDataSet数据集
privatevoidclustering(ClusterSetclusterList,MatrixtheDataSet)
//数据集的数据行列表
//对于每一个数据行,找出最接近它的簇类,增加此簇类的成员数目,
//同时减少上一次聚类时最接近这个数据行的簇类的成员数目
rows.size();
DataItemrow=rows.get(i);
ClusteroldNeighbor=row.mostNearestCluster;
//上一次聚类最接近的簇类
row.setNeighbors(clusterList);
Clustercluster=row.findMostNearestNeighbor();
//新的最接近的簇类
PointNDrowdata=row.rowdata;
//将数据添加到最接近的簇集中
PointND>
memList=cluster.memberList;
memList.add(rowdata);
cluster.counts++;
//从上次最接近的簇类中删除数据
//oldNeighbor为空时表示第一次聚类
if(oldNeighbor!
ArrayList<
oldmemList=oldNeighbor.memberList;
oldmemList.remove(rowdata);
oldNeighbor.counts--;
//intc=oldNeighbor.counts;
*K-Means聚类的接口
*调用聚类过程方法,当所有簇类的平均值不再改变时停止
*@paramclusterList簇类列表
*@paramdataSet数据集
privatevoidkMeansClustering(ClusterSetclusterList,MatrixtheDataSet)
//首先进行第一次聚类
this.clustering(clusterList,theDataSet);
K_Means.repeatCounts++;
//记录聚类次数
Cluster>
cluList=clusterList.clusterList;
intsize=cluList.size();
intnoChangeCounts=0;
cluList.size();
ClusteratomClu=cluList.get(i);
//更新簇的中心,如果中心不改变,则计数增1
if(atomClu.noChange())
noChangeCounts++;
//所有簇类的平均值不再改变时结束
while(noChangeCounts!
=size)
noChangeCounts=0;
this.clustering(clusterList,theDataSet);
cluList=clusterList.clusterList;
ClusteratomClu=cluList.get(i);
//更新簇的平均值
if(atomClu.noChange())
noChangeCounts++;
size=cluList.size();
//累计重复聚类次数
K_Means.repeatCounts++;
*根据聚类结果对数据集分类
privatevoidclassify(MatrixtheDataSet)
DataItemrowdata=rows.get(i);
ClusterSetneighbors=rowdata.neighborClusters;
Clustercluster=rowdata.mostNearestCluster;
//最接近簇类在簇集列表中的下标
intlabelIndex=neighbors.clusterList.indexOf(cluster);
labelIndex++;
//标记类标识
rowdata.setLabel("
"
+labelIndex);
*计算分类准确度
*@paramdataSet要测试的数据集
privatevoidcheckClassification(MatrixtheDataSet)throwsIOException
//System.out.println("
+K_Means.repeatCounts);
//计算分类正确率
intorigin=0;
//起始下标
intcorrectCount=0;
//正确分类的数据行数
intgroupCount;
//组的成员数
int[]tmp;
//存储类包含的成员数目
classData.size();
groupCount=classData.get(i);
tmp=newint[classData.size()];
//判别每一个组中的正确分类的元素个数
for(intj=origin;
j<
origin+groupCount;
j++)
DataItemitem=rows.get(j);
intlabel=Integer.parseInt(item.cLabel);
tmp[label-1]++;
//相应的类计数增1
//找出数组中的最大元素,以这个元素作为这个组的类计数
intmaxValue=0;
for(intk=0;
k<
tmp.length;
k++)
if(tmp[k]>
maxValue)
{
maxValue=tmp[k];
}
correctCount+=maxValue;
origin+=groupCount;
this.correctPercent=(float)correctCount/rows.size();
//保存分类说明及结果
if(this.correctPercent>
border)
System.out.println("
System.out.println("
+this.correctPercent*100+"
%"
this.saveFile();
//floatcorrectPercent=(float)correctCount/rows.size();
*计算分类准确度的公用接口
publicvoidcheckClassification()throwsIOException
this.checkClassification(this.dataSet);
*保存分类文件
privatevoidsaveFile()throwsIOException
System.out.println("
保存分类文件..."
FileclassFile=newFile("
class.txt"
if(classFile.exists())
classFile.delete();
FileOutputStreamfout=newFileOutputStream(classFile);
PrintWriterpWriter=newPrintWriter(fout);
rows=this.dataSet.rows;
pWriter.println("
p
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Kmeans 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)