聚类算法研究
聚类算法研究
摘要
本文首先了介绍聚类算法的分类,然后重点介绍了聚类算法下的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