最新C均值聚类实验报告共10页.docx
《最新C均值聚类实验报告共10页.docx》由会员分享,可在线阅读,更多相关《最新C均值聚类实验报告共10页.docx(17页珍藏版)》请在冰豆网上搜索。
![最新C均值聚类实验报告共10页.docx](https://file1.bdocx.com/fileroot1/2022-10/19/3b71e00f-9601-43c1-8c20-11e4729eb415/3b71e00f-9601-43c1-8c20-11e4729eb4151.gif)
最新C均值聚类实验报告共10页
C均值(jūnzhí)聚类实验报告
C均值(jūnzhí)聚类实验报告
一、C均值聚类的算法(suànfǎ)原理
聚类分析是指事先不知样本的类别,而利用样本的先验(xiānyàn)知识来构造分类器(无监督学习)
聚类准则(zhǔnzé)函数
在样本相似性度量的基础上,聚类分析还需要一定的准则函数,才能把真正属于同一类的样本聚合成一个类的子集,而把不同类的样本分离开来。
如果聚类准则函数选得好,聚类质量就会高。
同时,聚类准则函数还可以用来评价(píngjià)一种聚类结果的质量,如果聚类质量不满足要求,就要重复执行聚类过程,以优化结果。
在重复优化中,可以改变相似性度量,也可以选用新的聚类准则。
误差平方和准则(最常用的)
假定有混合样本集,采用某种相似性度量被聚合成c个分离开的子集,每个子集是一个类,它们分别包含个样本。
为了衡量聚类的质量,采用误差平方和聚类准则函数
式中为类中样本的均值:
是c个子集合的中心,可以用来代表c个类。
误差平方和聚类准则函数是样本与集合中心的函数。
在样本集X给定的情况下,其取值取决于c个集合“中心”。
它描述n个试验样本聚合成c个类时,所产生的总误差平方和越小越好。
误差平方和准则适用于各类样本比较密集且样本数目悬殊不大的样本分布。
C-均值聚类算法的核心思想是通过迭代把数据对象划分到不同的簇中,以求目标数最小化,从而使生成的簇尽可能地紧凑和独立。
首先(shǒuxiān),随机选取k个对象作为(zuòwéi)初始的k个簇的质心(zhìxīn);
然后,将其余对象根据其与各个簇质心的距离分配(fēnpèi)到最近的簇;再求新形成的簇的质心。
这个迭代重定位过程不断重复,直到(zhídào)目标函数最小化为止。
C-均值聚类算法使用的聚类准则函数是误差平方和准则:
为了使聚类结果优化,应该使准则最小化。
二、C均值聚类的实现步骤
C-均值算法步骤:
①给出n个混合样本,令,表示迭代运算次数,选取c个初始聚合中心
②计算每个样本与聚合中心的距离:
若
则
③令计算新的集合中心:
计算误差平方和值:
④对每个聚合中的每个样本,计算:
表示减少的部分。
表示增加的部分:
若,则把样本移到聚合中心中,并修改聚合中心和值。
⑤判断(pànduàn):
若则,返回(fǎnhuí)④。
否则(fǒuzé),算法结束。
三.编写(biānxiě)的程序:
#include
#include
#include
#include
#include
#include
usingnamespacestd;
doubledistance(doublea[4],doubleb[4])
{
//TODO:
改马氏距离(jùlí)
doubled0=a[0]-b[0];
doubled1=a[1]-b[1];
doubled2=a[2]-b[2];
doubled3=a[3]-b[3];
returnsqrt(d0*d0+d1*d1+d2*d2+d3*d3);
}
intmain()
{
//读取数据
doubledata[150][4];
ifstreamf("data.txt");
for(inti=0;i<150;i++)
f>>data[i][0]>>data[i][1]>>data[i][2]>>data[i][3];
f.close();
//归一化
doublem[4]={DBL_MAX,DBL_MAX,DBL_MAX,DBL_MAX};
doubleM[4]={-DBL_MAX,-DBL_MAX,-DBL_MAX,-DBL_MAX};
for(i=0;i<150;i++)
for(intj=0;j<4;j++)
{
if(data[i][j]m[j]=data[i][j];
if(data[i][j]>M[j])
M[j]=data[i][j];
}
for(i=0;i<150;i++)
for(intj=0;j<4;j++)
data[i][j]=(data[i][j]-m[j])/(M[j]-m[j]);
//打乱
//TODO:
使用(shǐyòng)随机排序
intrightLabels[150];
for(i=0;i<50;i++)
rightLabels[i]=0;
for(i=50;i<100;i++)
rightLabels[i]=1;
for(i=100;i<150;i++)
rightLabels[i]=2;
srand(time(NULL));
for(i=0;i<150;i++)
{
intj=rand()%150;
doubletmp;
tmp=data[i][0];data[i][0]=data[j][0];data[j][0]=tmp;
tmp=data[i][1];data[i][1]=data[j][1];data[j][1]=tmp;
tmp=data[i][2];data[i][2]=data[j][2];data[j][2]=tmp;
tmp=data[i][3];data[i][3]=data[j][3];data[j][3]=tmp;
inttmp2;
tmp2=rightLabels[i];
rightLabels[i]=rightLabels[j];
rightLabels[j]=tmp2;
}
//分类(fēnlèi)
intlabels[150];
doubleZ[3][4]={data[0][0],data[0][1],data[0][2],data[0][3],data[1][0],data[1][1],data[1][2],data[1][3],
data[2][0],data[2][1],data[2][2],data[2][3]};
intiterations=0;
while(true)
{
//cout<//<//<//<//cin.get();
iterations++;
//最小距离(jùlí)分类到label
for(inti=0;i<150;i++)
{
doubled0=distance(Z[0],data[i]);
doubled1=distance(Z[1],data[i]);
doubled2=distance(Z[2],data[i]);
if((d0labels[i]=0;
elseif(d1labels[i]=1;
else
labels[i]=2;
}
//计算均值(jūnzhí)为新聚类中心到Z
doublesum[3][4]={0.0};
intcount[3]={0};
for(i=0;i<150;i++)
{
intlabel=labels[i];
sum[label][0]+=data[i][0];
sum[label][1]+=data[i][1];
sum[label][2]+=data[i][2];
sum[label][3]+=data[i][3];
count[label]++;
}
boolchanged=false;
for(i=0;i<3;i++)
for(intj=0;j<4;j++)
{
if(Z[i][j]!
=sum[i][j]/count[i])//可以加入(jiārù)e比较
{
Z[i][j]=sum[i][j]/count[i];
changed=true;
}
}
//聚类中心(zhōngxīn)没改变则退出
if(!
changed)
break;
}
//输出(shūchū)
intcount[3]={0};
for(i=0;i<150;i++)
{
cout<count[labels[i]]++;
}
cout<<<"iterations:
"<<<"label0count:
"<<<"label1count:
"<<<"label2count:
"<cin.get();
return0;
}
四.运行(yùnxíng)结果:
0.166667
0.166667
0.389831
0.375
0
B
0.138889
0.416667
0.067797
0
1
A
0.472222
0.083333
0.677966
0.583333
0
C
0.583333
0.333333
0.779661
0.875
2
C
0.25
0.875
0.084746
0
1
A
0.194444
0
0.423729
0.375
0
B
0.194444
0.583333
0.084746
0.041667
1
A
0.5
0.375
0.627119
0.541667
0
B
0.416667
0.291667
0.525424
0.375
0
B
0.75
0.5
0.627119
0.541667
2
B
0.138889
0.458333
0.101695
0.041667
1
A
0.25
0.291667
0.491525
0.541667
0
B
0.333