zoukankan      html  css  js  c++  java
  • 聚类算法的设计与实现

     常用的聚类算法有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
    
    
  • 相关阅读:
    log4net GetLogger(source).IsInfoEnabled = false
    nginx配置
    mysql数据库备份
    按序号批量更新某个字段
    MySql 执行 DELETE/UPDATE时,报 Error Code: 1175错误
    ef学习记录
    vue-cli3实行路径联想
    GitHub分支创建及合并
    Git本地分支和远程分支关联
    uniapp(三)
  • 原文地址:https://www.cnblogs.com/wj204/p/3138075.html
Copyright © 2011-2022 走看看