聚类算法研究

聚类算法研究

摘要

本文首先了介绍聚类算法的分类,然后重点介绍了聚类算法下的k-means 算法的基本概念,处理流程。另外举出了一个源程序代码及对此代码的实现。

关键词:聚类算法,k-means算法,源程序,聚类算法分类

1.聚类算法概念

在自然科学和社会科学中,存在着大量的分类问题。所谓类,通俗地说,就是指相似元素的集合。聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法。聚类分析起源于分类学,在古老的分类学中,人们主要依靠经验和专业知识来实现分类,很少利用数学工具进行定量的分类。随着人类科学技术的发展,对分类的要求越来越高,以致有时仅凭经验和专业知识难以确切地进行分类,于是人们逐渐地把数学工具引用到了分类学中,形成了数值分类学,之后又将多元分析的技术引入到数值分类学形成了聚类分析。聚类分析内容非常丰富,有系统聚类法、有序样品聚类法、动态聚类法、模糊聚类法、图论聚类法、聚类预报法等。

2.聚类算法的分类

2.1K-MEANS算法

k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。

2.2 K-MEDOIDS算法

K-MEANS有其缺点:产生类的大小相差不会很大,对于脏数据很敏感。改进的算法:k—medoids 方法。这儿选取一个对象叫做mediod来代替上面的中心的作用,这样的一个medoid就标识了这个类。这种算法对于脏数据和异常数据不敏感,但计算量显然要比K均值要大,一般只适合小数据量。

2.3 Clara算法

K-medoids算法不适合于大数据量的计算,但是Clara算法是一种基于采用的方法,它能够处理大量的数据。Clara算法的思想就是用实际数据的抽样来代替整个数据,然后再在这些抽样的数据上利用K-medoids算法得到最佳的medoids。Clara算法从实际数据中抽取多个采样,在每个采样上都用K-medoids 算法得到相应的(O1,O2…Oi…Ok),然后在这当中选取E最小的一个作为最终的结果。

2.4Clarans算法

Clara算法的效率取决于采样的大小,一般不太可能得到最佳的结果。在Clara算法的基础上,又提出了Clarans的算法,与Clara算法不同的是:在Clara 算法寻找最佳的medoids的过程中,采样都是不变的。而Clarans算法在每一次循环的过程中所采用的采样都是不一样的。与上面所讲的寻找最佳medoids的过程不同的是,必须人为地来限定循环的次数。

3.k-means算法

3.1简介

k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。

k-means 算法的工作过程说明如下:首先从n个数据对象任意选择 k 个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数. k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。

3.2处理流程

(1)从 n个数据对象任意选择 k 个对象作为初始聚类中心;

(2)循环(3)到(4)直到每个聚类不再发生变化为止;

(3)根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;

(4)重新计算每个(有变化)聚类的均值(中心对象)。

k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。 k-means 算法的工作过程说明如下:首先从n个数据对象任意选择 k 个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数. k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。

4.k-means算法源代码

#include

#include

#include

int N;//数据个数

int K;//集合个数

int * CenterIndex;//初始化质心数组的索引

double * Center;//质心集合

double * CenterCopy;//质心集合副本

double * AllData;//数据集合

double ** Cluster;//簇的集合#include

int * Top;//集合中元素的个数,也会用作栈处理

//随机生成k个数x(0<=x<=n-1)作为起始的质心集合

void CreateRandomArray(int n, int k,int * center)

{

int i=0;

int j=0;

srand( (unsigned)time( NULL ) );

for( i=0;i

{

int a=rand()%n;//判重

for(j=0;j

if(center[j]==a)//重复

break;

if(j>=i)//如果不重复,加入

center[i]=a;

else

i--;//如果重复,本次重新随机生成

}

}

//返回距离最小的质心的序号

int GetIndex(double value,double * center)

{

int i=0;

int index=i;//最小的质心序号

double min=fabs(value-center[i]);//距质心最小距离

for(i=0;i

{

if(fabs(value-center[i])

{

index=i;

min=fabs(value-center[i]);

}

}

return index;

}

void CopyCenter()//拷贝质心数组到副本

{

int i=0;

for(i=0;i

CenterCopy[i]=Center[i];

}

void InitCenter()//初始化质心,随机生成法

{

int i=0;

CreateRandomArray(N,K,CenterIndex);//产生随机的K个

for(i=0;i

{

Center[i]=AllData[CenterIndex[i]];//将对应数据赋值给质心数组// printf("%f ",Center[i]); //测试用

}

CopyCenter();//拷贝到质心副本

}

void AddToCluster(int index,double value)//加入一个数据到一个Cluster[index]集合

{

Cluster[index][Top[index]++]=value;//这里同进栈操作

}

//重新计算簇集合

void UpdateCluster()

{

int i=0;

int tindex;

//将所有的集合清空,即将TOP置0

for(i=0;i

Top[i]=0;

for(i=0;i

{

tindex=GetIndex(AllData[i],Center);//得到与当前数据最小的质心索引

AddToCluster(tindex,AllData[i]); //加入到相应的集合中

}

}

void UpdateCenter()//重新计算质心集合,对每一簇集合中的元素加总求平均即可{

int i=0;

int j=0;

double sum=0;

for(i=0;i

{

sum=0; //计算簇i的元素和

for(j=0;j

sum+=Cluster[i][j];

if(Top[i]>0)//如果该簇元素不为空

Center[i]=sum/Top[i];//求其平均值

}

}

bool IsEqual(double * center1 ,double * center2)//判断2数组元素是否相等{

int i;

for(i=0;i

{

if(fabs(center1[i]!=center2[i]))

return false;

}

return true;

}

void Print()//打印聚合结果

{

int i,j;

printf("\n-------------------------------------- ");

for(i=0;i

{

printf("\n第%d组: 质心(%f) :\n",i+1,Center[i]);

for(j=0;j

{

printf("%f ",Cluster[i][j]);

}

}

void InitData()//初始化聚类的各种数据

{

int i=0;

int a;

printf("输入数据个数: ");

scanf("%d",&N);

printf("输入簇个数: ");

scanf("%d",&K);

if(K>N)

{

exit(0);

}

Center=new double[K]; //为质心集合申请空间

CenterIndex=new int[K];//为质心集合索引申请空间

CenterCopy=new double[K]; //为质心集合副本申请空间

Top=new int[K];

AllData=new double[N]; //为数据集合申请空间

Cluster=(double **)malloc(sizeof(double *)*K);//为簇集合申请空间

//初始化K个簇集合

for(i=0;i

{

Cluster[i]=(double *)malloc(sizeof(double)*N);

Top[i]=0;

}

printf("输入%d数据: ",N);

for(i=0;i

{

scanf("%d",&(a));

AllData[i]=a;

}

InitCenter();//初始化质心集合

UpdateCluster();//初始化K个簇集合

}

void free()//释放申请的空间

delete Center;

delete CenterIndex;

delete CenterCopy;

delete Top;

delete AllData;

free(Cluster);

}

/*

算法描述:

K均值算法:

给定类的个数K,将N个对象分到K个类中去,

使得类内对象之间的相似性最大,而类之间的相似性最小。

*/

int main()

{

int Flag=1;//迭代标志,若为false,则迭代结束

int i=0;

InitData();//初始化数据

/* for(int j=0;j

printf("%f ",Center[j]);

*/

while(Flag)//开始迭代

{

UpdateCluster();//更新各个聚类

UpdateCenter();//更新质心数组

if(IsEqual(Center,CenterCopy))//如果本次迭代与前次的质心聚合相等,即已收敛,结束退出

{

Flag=0;

}

else//否则将质心副本置为本次迭代得到的的质心集合

{

CopyCenter();//将质心副本置为本次迭代得到的的质心集合

}

/* i++;

printf("\n%d times",i); //测试用

for(int j=0;j

printf("%f ",Center[j]);*/

}

Print();//输出结果

free();

getchar();

return 0;

}

5. 测试及运行结果

实验截图1

实验截图2

参考文献

1.https://www.360docs.net/doc/0d10005386.html,/view/31854.htm#sub31854

2.https://www.360docs.net/doc/0d10005386.html,/view/936564e0524de518964b7dc4.html

3.https://www.360docs.net/doc/0d10005386.html,/view/470258e59b89680203d82598.html

4.https://www.360docs.net/doc/0d10005386.html,/view/d1c62837ee06eff9aef8070

5.html

相关文档
最新文档