聚类算法的设计与实现

 常用的聚类算法有K-Means(K均值聚类算法)、DBSCAN和OPTICS等。

K均值聚类算法的相关信息自行从网上获取。简单介绍如下:

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

K-Means 算法的步骤:

(1)选K个初始聚类中心,z1(1),z2(1),…,zK(1),其中括号内的序号为寻找聚类中心的迭代运算的次序号。聚类中心的向量值可任意设定,例如可选开始的K个模式样本的向量值作为初始聚类中心。

(2)逐个将需分类的模式样本{x}按最小距离准则分配给K个聚类中心中的某一个zj(1)。假设i=j时,其中k为迭代运算的次序号,第一次迭代k=1,Sj表示第j个聚类,其聚类中心为zj。

(3)计算各个聚类中心的新的向量值,zj(k+1),j=1,2,…,K。求各聚类域中所包含样本的均值向量;其中Nj为第j个聚类域Sj中所包含的样本个数。以均值向量作为新的聚类中心,可使如下聚类准则函数最小:在这一步中要分别计算K个聚类中的样本均值向量,所以称之为K-均值算法。

(4)若j=1,2,…,K,则返回第二步,将模式样本逐个重新分类,重复迭代运算;

若本次迭代与前次的质心聚合相等,即已收敛,计算结束。


实现代码(参考自http://blog.csdn.net/blue4689/article/details/6629488):
  1 #include <stdio.h> 

  2 #include <math.h>

  3 #include <stdlib.h>

  4 #include <time.h>

  5 #define TRUE            1

  6 #define FALSE           0 

  7 int N;//数据个数

  8 int K;//集合个数

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

 10 double * Center;//质心集合

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

 12 double * AllData;//数据集合

 13 double ** Cluster;//簇的集合

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

 15 

 16  

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

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

 19 {

 20     int i=0;

 21     int j=0;    

 22     srand( (unsigned)time( NULL ) );

 23     for( i=0;i<k;++i)//随机生成k个数

 24     {

 25         int a=rand()%n;

 26         //判重

 27         for(j=0;j<i;j++)

 28         {

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

 30             {

 31                 break;

 32             }

 33         }

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

 35         {

 36             center[i]=a;

 37         }

 38         else

 39         {

 40             i--;

 41             //如果重复,本次重新随机生成

 42         }

 43     }     

 44 }

 45  

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

 47 int GetIndex(double value,double * center)

 48 {

 49     int i=0;

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

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

 52     for(i=0;i<K;i++)

 53     {

 54         if(fabs(value-center[i])<min)//如果比当前距离还小,更新最小的质心序号和距离值

 55         {

 56              index=i;

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

 58         }

 59     }

 60     return index;

 61 }

 62  

 63 //拷贝质心数组到副本

 64 void CopyCenter()

 65 {

 66     int i=0;

 67     for(i=0;i<K;i++)

 68     {

 69         CenterCopy[i]=Center[i];

 70     }

 71 }

 72 //初始化质心,随机生成法

 73 void InitCenter()

 74 {

 75     int i=0;

 76     CreateRandomArray(N,K,CenterIndex);//产生随机的K个<N的不同的序列

 77     for(i=0;i<K;i++)

 78     {

 79         Center[i]=AllData[CenterIndex[i]];//将对应数据赋值给质心数组

 80     }

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

 82 }

 83 //加入一个数据到一个Cluster[index]集合

 84 void AddToCluster(int index,double value)

 85 {

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

 87 } 

 88 

 89 //重新计算簇集合

 90 void UpdateCluster()

 91 {    

 92     int i=0;

 93     int tindex;

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

 95     for(i=0;i<K;i++)

 96     {

 97         Top[i]=0;

 98     }

 99     for(i=0;i<N;i++)

100     {

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

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

103     }

104 }

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

106 void UpdateCenter()

107 {

108     int i=0;

109     int j=0;

110     double sum=0;

111     for(i=0;i<K;i++)

112     {

113         sum=0;    

114         //计算簇i的元素和

115         for(j=0;j<Top[i];j++)

116          {

117              sum+=Cluster[i][j];

118          }

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

120         {

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

122         }

123     }

124 }

125 //判断2数组元素是否相等

126 int IsEqual(double * center1 ,double * center2)

127 {

128     int i;

129     for(i=0;i<K;i++)

130     {

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

132          {

133              return FALSE;

134          }

135     }

136     return TRUE;

137 }

138 //打印聚合结果

139 void Print()

140 {

141     int i,j;

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

143     for(i=0;i<K;i++)

144     {

145          printf("第%d组: 质心(%f)\t",i,Center[i]);

146           for(j=0;j<Top[i];j++)

147           {

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

149           }  

150           printf("\n");

151     }     

152 }

153 //初始化聚类的各种数据

154 void InitData()

155 {

156     int i=0;

157     int a;

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

159     scanf("%d",&N);

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

161     scanf("%d",&K);    

162     if(K>N)

163     {

164         exit(0);

165     }

166     Center=(double *)malloc(sizeof(double)*K);//为质心集合申请空间

167     CenterIndex=(int *)malloc(sizeof(int)*K);//为质心集合索引申请空间

168     CenterCopy=(double *)malloc(sizeof(double)*K);//为质心集合副本申请空间

169     Top=(int *)malloc(sizeof(int)*K); 

170     AllData=(double *)malloc(sizeof(double)*N);//为数据集合申请空间

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

172     //初始化K个簇集合

173     for(i=0;i<K;i++)

174     {

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

176         Top[i]=0;

177     }

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

179     for(i=0;i<N;i++)

180     {

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

182         AllData[i]=a;

183     }

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

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

186      

187 }

188 /*

189 算法描述:

190 K均值算法:

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

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

193 */

194 main()

195 {

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

197     int i=0;

198      InitData();//初始化数据      

199      while(Flag)//开始迭代

200      {

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

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

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

204          {

205              Flag=0;

206          }

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

208          {

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

210          }

211      }

212      Print();//输出结果

213 }
View Code

 



                            

你可能感兴趣的:(算法)