最近在苦于思考kmeans算法的MPI并行化,花了两天的时间把该算法看懂和实现了串行版。

  聚类问题就是给定一个元素集合V,其中每个元素具有d个可观察属性,使用某种算法将V划分成k个子集,要求每个子集内部的元素之间相异度尽可能低,而不同子集的元素相异度尽可能高。

  下面是google到该算法的一个流程图,表意清楚:

  1、随机选取数据集中的k个数据点作为初始的聚类中心:

  

  2、分别计算每个数据点到每个中心的距离,选取距离最短的中心点作为其聚类中心:

  

  3、利用目前得到的聚类重新计算中心点:

  

  4、重复步骤2和3直到收敛(达到最大迭代次数或聚类中心不再移动):

  

  code:

 #include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h> int K,N,D; //聚类的数目,数据量,数据的维数
float **data; //存放数据
int *in_cluster; //标记每个点属于哪个聚类
float **cluster_center; //存放每个聚类的中心点 float **array(int m,int n);
void freearray(float **p);
float **loadData(int *k,int *d,int *n);
float getDistance(float avector[],float bvector[],int n);
void cluster();
float getDifference();
void getCenter(int in_cluster[]); int main()
{
int i,j,count=;
float temp1,temp2;
data=loadData(&K,&D,&N);
printf("Data sets:\n");
for(i=;i<N;i++)
for(j=;j<D;j++){
printf("%-8.2f",data[i][j]);
if((j+)%D==) putchar('\n');
}
printf("-----------------------------\n"); srand((unsigned int)(time(NULL))); //随机初始化k个中心点
for(i=;i<K;i++)
for(j=;j<D;j++)
cluster_center[i][j]=data[(int)((double)N*rand()/(RAND_MAX+1.0))][j]; cluster(); //用随机k个中心点进行聚类
temp1=getDifference(); //第一次中心点和所属数据点的距离之和
count++;
printf("The difference between data and center is: %.2f\n\n", temp1); getCenter(in_cluster);
cluster(); //用新的k个中心点进行第二次聚类
temp2=getDifference();
count++;
printf("The difference between data and center is: %.2f\n\n",temp2); while(fabs(temp2-temp1)!=){ //比较前后两次迭代,若不相等继续迭代
temp1=temp2;
getCenter(in_cluster);
cluster();
temp2=getDifference();
count++;
printf("The %dth difference between data and center is: %.2f\n\n",count,temp2);
} printf("\nThe total number of cluster is: %d\n",count); //统计迭代次数
//system("pause"); //gcc编译需删除
return ;
} //动态创建二维数组
float **array(int m,int n)
{
int i;
float **p;
p=(float **)malloc(m*sizeof(float *));
p[]=(float *)malloc(m*n*sizeof(float));
for(i=;i<m;i++) p[i]=p[i-]+n;
return p;
} //释放二维数组所占用的内存
void freearray(float **p)
{
free(*p);
free(p);
} //从data.txt导入数据,要求首行格式:K=聚类数目,D=数据维度,N=数据量
float **loadData(int *k,int *d,int *n)
{
int i,j;
float **arraydata;
FILE *fp;
if((fp=fopen("data.txt","r"))==NULL) fprintf(stderr,"cannot open data.txt!\n");
if(fscanf(fp,"K=%d,D=%d,N=%d\n",k,d,n)!=) fprintf(stderr,"load error!\n");
arraydata=array(*n,*d); //生成数据数组
cluster_center=array(*k,*d); //聚类的中心点
in_cluster=(int *)malloc(*n * sizeof(int)); //每个数据点所属聚类的标志数组
for(i=;i<*n;i++)
for(j=;j<*d;j++)
fscanf(fp,"%f",&arraydata[i][j]); //读取数据点
return arraydata;
} //计算欧几里得距离
float getDistance(float avector[],float bvector[],int n)
{
int i;
float sum=0.0;
for(i=;i<n;i++)
sum+=pow(avector[i]-bvector[i],);
return sqrt(sum);
} //把N个数据点聚类,标出每个点属于哪个聚类
void cluster()
{
int i,j;
float min;
float **distance=array(N,K); //存放每个数据点到每个中心点的距离
//float distance[N][K]; //也可使用C99变长数组
for(i=;i<N;++i){
min=9999.0;
for(j=;j<K;++j){
distance[i][j] = getDistance(data[i],cluster_center[j],D);
//printf("%f\n", distance[i][j]);
if(distance[i][j]<min){
min=distance[i][j];
in_cluster[i]=j;
}
}
printf("data[%d] in cluster-%d\n",i,in_cluster[i]+);
}
printf("-----------------------------\n");
free(distance);
} //计算所有聚类的中心点与其数据点的距离之和
float getDifference()
{
int i,j;
float sum=0.0;
for(i=;i<K;++i){
for(j=;j<N;++j){
if(i==in_cluster[j])
sum+=getDistance(data[j],cluster_center[i],D);
}
}
return sum;
} //计算每个聚类的中心点
void getCenter(int in_cluster[])
{
float **sum=array(K,D); //存放每个聚类中心点
//float sum[K][D]; //也可使用C99变长数组
int i,j,q,count;
for(i=;i<K;i++)
for(j=;j<D;j++)
sum[i][j]=0.0;
for(i=;i<K;i++){
count=; //统计属于某个聚类内的所有数据点
for(j=;j<N;j++){
if(i==in_cluster[j]){
for(q=;q<D;q++)
sum[i][q]+=data[j][q]; //计算所属聚类的所有数据点的相应维数之和
count++;
}
}
for(q=;q<D;q++)
cluster_center[i][q]=sum[i][q]/count;
}
printf("The new center of cluster is:\n");
for(i = ; i < K; i++)
for(q=;q<D;q++){
printf("%-8.2f",cluster_center[i][q]);
if((q+)%D==) putchar('\n');
}
free(sum);
}

  

  该程序支持不同维度的数据集,一个示例的数据集 data.txt如下:

  K=3,D=3,N=15

  -25 22.2 35.34
  31.2 -14.4 23
  32.02 -23 24.44
  -25.35 36.3 -33.34
  -20.2 27.333 -28.22
  -15.66 17.33 -23.33
  26.3 -31.34 16.3
  -22.544 16.2 -32.22
  12.2 -15.22 22.11
  -41.241 25.232 -35.338
  -22.22 45.22 23.55
  -34.22 50.14 30.98
  15.23 -30.11 20.987
  -32.5 15.3 -25.22
  -38.97 20.11 33.22 

kmeans算法c语言实现,能对不同维度的数据进行聚类的更多相关文章

  1. kmeans算法

    # coding:utf-8 import numpy as np import matplotlib.pyplot as plt def dis(x, y): #计算距离 return np.sum ...

  2. Kmeans算法与KNN算法的区别

    最近研究数据挖掘的相关知识,总是搞混一些算法之间的关联,俗话说好记性不如烂笔头,还是记下了以备不时之需. 首先明确一点KNN与Kmeans的算法的区别: 1.KNN算法是分类算法,分类算法肯定是需要有 ...

  3. k-means算法之见解(一)

    k-menas算法之见解 主要内容: 一.引言 二.k-means聚类算法 一.引言: 先说个K-means算法很高大上的用处,来开始新的算法学习.美国竞选总统,选票由公民投出,总统由大家决定.在20 ...

  4. K-means算法的原理、优缺点及改进(转)

    文章内容转载自:http://blog.csdn.net/sinat_35512245/article/details/55051306                                ...

  5. 数学建模及机器学习算法(一):聚类-kmeans(Python及MATLAB实现,包括k值选取与聚类效果评估)

    一.聚类的概念 聚类分析是在数据中发现数据对象之间的关系,将数据进行分组,组内的相似性越大,组间的差别越大,则聚类效果越好.我们事先并不知道数据的正确结果(类标),通过聚类算法来发现和挖掘数据本身的结 ...

  6. 数据挖掘经典算法——K-means算法

    算法描述 K-means算法是一种被广泛使用的基于划分的聚类算法,目的是将n个对象会分成k个簇.算法的具体描述如下: 随机选取k个对象作为簇中心: Do 计算所有对象到这k个簇中心的距离,将距离最近的 ...

  7. 机器学习实战之K-Means算法

    一,引言 先说个K-means算法很高大上的用处,来开始新的算法学习.我们都知道每一届的美国总统大选,那叫一个竞争激烈.可以说,谁拿到了各个州尽可能多的选票,谁选举获胜的几率就会非常大.有人会说,这跟 ...

  8. 【转】机器学习实战之K-Means算法

    一,引言 先说个K-means算法很高大上的用处,来开始新的算法学习.我们都知道每一届的美国总统大选,那叫一个竞争激烈.可以说,谁拿到了各个州尽可能多的选票,谁选举获胜的几率就会非常大.有人会说,这跟 ...

  9. RFM模型的变形LRFMC模型与K-means算法的有机结合

    应用场景: 可以应用在不同行业的客户分类管理上,比如航空公司,传统的RFM模型不再适用,通过RFM模型的变形LRFMC模型实现客户价值分析:基于消费者数据的精细化营销 应用价值: LRFMC模型构建之 ...

随机推荐

  1. centos-5.5安装vmvare tools

    centos-5.5安装vmvare tools 虚拟机管理,安装tools 找到VMwareTools压缩包 解压到Desktop,桌面 终端进入桌面 执行程序# ./vmware-install. ...

  2. 创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表

    创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表 创建数据模型类(POCO类) 在Models文件夹下添 ...

  3. C++如何调用C#开发的dll

    序言 本文介绍一个C++如何调用C#开发的dll实例. 前言 C++编写的程序为非托管代码,C#编写的程序为托管代码.托管代码虽然提供了其他开发平台没有的许多优势,但由于前期系统及历史版本很多使用的是 ...

  4. 【原创】kafka admin源代码分析

    admin包定义了命令行的一些实现 一.AdminOperationException.scala 一个异常类,表示执行admin命令时候抛出的异常 二.AdminUtils.scala admin一 ...

  5. 关系数据库SQL之高级数据查询:去重复、组合查询、连接查询、虚拟表

    前言 接上一篇关系数据库SQL之基本数据查询:子查询.分组查询.模糊查询,主要是关系型数据库基本数据查询.包括子查询.分组查询.聚合函数查询.模糊查询,本文是介绍一下关系型数据库几种高级数据查询SQL ...

  6. PPT里面添加3Dvia Composer Player 控件

    本实例是Office 2013 版本 1打开文件-选项---自定义功能区--主选项卡 ---开发工具 :如图 4然后将在菜单栏里面看到 开发工具 5然后将出出一个十字 绘制你想要的区域 6 鼠标右击 ...

  7. UDS(ISO14229-2006) 汉译(No.7 应用层协议)【未完,待续】

    7.1定义 应用层协议通常作为确认消息的传输,意味着从客户端发送的每一个请求都将有由服务器端产生的与之相对的响应. 唯一的例外在于:例如使用了功能寻址方式,或者该请求/指示没有指定生成响应/确定的少数 ...

  8. 使用TabPageIndicator的样式问题

    在使用TabPageIndicator往往会出现一些样式问题,导致看不到字,下面是总结的步骤: 1.布局<LinearLayout xmlns:android="http://sche ...

  9. entityframework学习笔记--001

    最近想重新好好学习一下entityframework,于是在院子里找到了一篇不错的博客.下面把学习的过程记录下来,方便以后复习. 学习过程参考大神的博客:http://www.cnblogs.com/ ...

  10. 自己动手写ORM的感受

    之前看到奋斗前辈和时不我待前辈的自己动手写ORM系列博客,感觉讲解的通俗易懂,清晰透彻.作为一个菜鸟,闲来也想着自己写一个ORM,一来加深自己对 ORM的理解,以求对EF,NHibernate等ROM ...