1.   简介:

K-MEANS算法是输入聚类个数k,以及包含 n个数据对象的数据库,输出满足方差最小标准k个聚类的一种算法。k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。

聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。

2.   算法流程

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

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

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

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

3.   常见问题

1)      初始质心的选择

选择适当的初始质心是基本kmeans算法的关键步骤。常见的方法是随机的选取初始质心,但是这样簇的质量常常很差。处理选取初始质心问题的一种常用技术是:多次运行,每次使用一组不同的随机初始质心,然后选取具有最小SSE(误差的平方和)的簇集。这种策略简单,但是效果可能不好,这取决于数据集和寻找的簇的个数。

第二种有效的方法是,取一个样本,并使用层次聚类技术对它聚类。从层次聚类中提取K个簇,并用这些簇的质心作为初始质心。该方法通常很有效,但仅对下列情况有效:(1)样本相对较小,例如数百到数千(层次聚类开销较大);(2)K相对于样本大小较小

第三种选择初始质心的方法,随机地选择第一个点,或取所有点的质心作为第一个点。然后,对于每个后继初始质心,选择离已经选取过的初始质心最远的点。使用这种方法,确保了选择的初始质心不仅是随机的,而且是散开的。但是,这种方法可能选中离群点。此外,求离当前初始质心集最远的点开销也非常大。为了克服这个问题,通常该方法用于点样本。由于离群点很少(多了就不是离群点了),它们多半不会在随机样本中出现。计算量也大幅减少。

2)      距离的度量

  常用的距离度量方法包括:欧几里得距离和余弦相似度。两者都是评定个体间差异的大小的。欧几里得距离度量会受指标不同单位刻度的影响,所以一般需要先进行标准化,同时距离越大,个体间差异越大;空间向量余弦夹角的相似度度量不会受指标刻度的影响,余弦值落于区间[-1,1],值越大,差异越小。

本次实验采用欧几里得距离度量。

3)      算法停止条件

计算各个聚类中心的中心向量值Zj(k+1),j=1.2.3…k,如果Zj(k+1)=Zj(k)则可以停止。

算法实现

1.   实验数据--data.txt:

实验数据为处理后的IRIS数据集。数据集包含150个数据集,分为3类,每类50个数据,每个数据包含4个属性。可通过花萼长度,花萼宽度,花瓣长度,花瓣宽度4个属性预测鸢尾花卉属于(Setosa,Versicolour,Virginica)三个种类中的哪一类。

文件内容:

K=3,D=4,N=150

5.1  3.5  1.4  0.2

4.9  3     1.4  0.2

4.7  3.2  1.3  0.2

4.6  3.1  1.5  0.2

5     3.6  1.4  0.2

5.4  3.9  1.7  0.4

4.6  3.4  1.4  0.3

5     3.4  1.5  0.2

数据说明:

第一行表示分为三类,4个特征,150个数据后面依次为数据信息。

2.   输出数据—result.txt

输出数据输出实验数据聚类后的分类信息,与真实信息对比来分析程序聚类准确率。

文件内容:

0

2

0

1

0

数据说明:

0,1,2依次对应表示Setosa,Versicolour,Virginica三类花。

3.   程序运行截图:

程序每次计算输出新的聚类中心点,中心向量值(即各点与聚类中心的距离和平均值),以及分类信息,当中心向量值不变,聚类完成

源代码

#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=0;float temp1,temp2;data=loadData(&K,&D,&N);printf("Data sets:\n");for(i=0;i<N;i++)for(j=0;j<D;j++){printf("%-8.2f",data[i][j]);if((j+1)%D==0)    putchar('\n');}printf("-----------------------------\n");srand((unsigned int)(time(NULL)));  //随机初始化k个中心点for(i=0;i<K;i++)for(j=0;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)!=0){   //比较前后两次迭代,若不相等继续迭代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 0;
}//动态创建二维数组
float **array(int m,int n)
{int i;float **p;p=(float **)malloc(m*sizeof(float *));p[0]=(float *)malloc(m*n*sizeof(float));for(i=1;i<m;i++)    p[i]=p[i-1]+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)!=3)        fprintf(stderr,"load error!\n");arraydata=array(*n,*d);  //生成数据数组cluster_center=array(*k,*d);  //聚类的中心点in_cluster=(int *)malloc(*n * sizeof(int));  //每个数据点所属聚类的标志数组for(i=0;i<*n;i++)for(j=0;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=0;i<n;i++)sum+=pow(avector[i]-bvector[i],2);return sqrt(sum);
}//把N个数据点聚类,标出每个点属于哪个聚类
void cluster()
{int i,j;float min;float **distance=array(N,K);  //存放每个数据点到每个中心点的距离//float distance[N][K];  //也可使用C99变长数组FILE *fp2;if((fp2=fopen("result.txt","w"))==NULL) {printf("File cannot be opened/n");exit(0);}for(i=0;i<N;++i){min=9999.0;for(j=0;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] 属于类-%d\n",i,in_cluster[i]);fprintf(fp2,"%d \n",in_cluster[i]);//写入文件}printf("-----------------------------\n");free(distance);
}//计算所有聚类的中心点与其数据点的距离之和
float getDifference()
{int i,j;float sum=0.0;for(i=0;i<K;++i){for(j=0;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=0;i<K;i++)for(j=0;j<D;j++)sum[i][j]=0.0;for(i=0;i<K;i++){count=0;  //统计属于某个聚类内的所有数据点for(j=0;j<N;j++){if(i==in_cluster[j]){for(q=0;q<D;q++)sum[i][q]+=data[j][q];  //计算所属聚类的所有数据点的相应维数之和count++;}}for(q=0;q<D;q++)cluster_center[i][q]=sum[i][q]/count;}printf("The new center of cluster is:\n");for(i = 0; i < K; i++)for(q=0;q<D;q++){printf("%-8.2f",cluster_center[i][q]);if((q+1)%D==0)    putchar('\n');}free(sum);
}

基于C++的K-means聚类算法实现相关推荐

  1. k means聚类算法_一文读懂K-means聚类算法

    1.引言 什么是聚类?我们通常说,机器学习任务可以分为两类,一类是监督学习,一类是无监督学习.监督学习:训练集有明确标签,监督学习就是寻找问题(又称输入.特征.自变量)与标签(又称输出.目标.因变量) ...

  2. k means聚类算法_K-Means 聚类算法 20210108

    说到聚类,应先理解聚类和分类的区别 聚类和分类最大的不同在于:分类的目标是事先已知的,而聚类则不一样,聚类事先不知道目标变量是什么,类别没有像分类那样被预先定义出来. K-Means 聚类算法有很多种 ...

  3. OpenCV官方文档 理解k - means聚类

    理解k - means聚类 目标 在这一章中,我们将了解k - means聚类的概念,它是如何工作等. 理论 我们将这个处理是常用的一个例子. t恤尺寸问题 考虑一个公司要发布一个新模型的t恤. 显然 ...

  4. k均值聚类算法(K Means)及其实战案例

    算法说明 K均值聚类算法其实就是根据距离来看属性,近朱者赤近墨者黑.其中K表示要聚类的数量,就是说样本要被划分成几个类别.而均值则是因为需要求得每个类别的中心点,比如一维样本的中心点一般就是求这些样本 ...

  5. OpenCV的k - means聚类 -对图片进行颜色量化

    OpenCV的k - means聚类 目标 学习使用cv2.kmeans()数据聚类函数OpenCV 理解参数 输入参数 样品:它应该的np.float32数据类型,每个特性应该被放在一个单独的列. ...

  6. K-Means(K均值聚类算法)

    K-Means(K均值聚类算法) 1.前言 要学习聚类算法就要知道聚类学习算法是什么,为什么要学习聚类学习聚类学习算法,有什么用途,下面就简单的做一下介绍,并且详细的说明k-means均值聚类学习算法 ...

  7. 基于Python的k均值聚类不同规格的商品名

    基于Python的k均值聚类不同规格的商品名 前言 聚类的目标是使得同一簇内的点之间的距离较短,而不同簇中点之间的距离较大.以此来区分不同的群体. 本篇讲述使用k均值算法对超市购物记录集中的商品名称进 ...

  8. k均值聚类算法python_K均值和其他聚类算法:Python快速入门

    k均值聚类算法python This post was originally published here 这篇文章最初发表在这里 Clustering is the grouping of obje ...

  9. python实现的基于NMF的多图聚类算法

    python实现的基于NMF的多图聚类算法的封装 代码均由论文复现 文章目录 python实现的基于NMF的多图聚类算法的封装 前言 参考论文 一.NMF 二.Mjnmf 总结 前言 怕忘记干了这个事 ...

  10. K-means(K均值聚类算法)算法笔记

    K-means(K均值聚类算法)算法笔记 K-means 算法,是比较简单的无监督的算法,通过设定好初始的类别k,然后不断循环迭代,将给定的数据自动分为K个类别.事实上,大家都知道K-means是怎么 ...

最新文章

  1. 这个假发太逼真!GAN帮你换发型,毫无违和感!
  2. Kubernetes面试题超详细总结
  3. 定时任务--mysql数据库备份
  4. win7系统安装信息服务器不可用怎么办,win7系统提示rpc服务器不可用怎么办
  5. 用FFmpeg搭建基于CNN的视频分析方案
  6. mips j指令_MIPS的基本实现
  7. Python3.1-标准库之Numpy
  8. 揭秘2019双11背后的云网络 – 双11网络架构和洛神系统
  9. mysql安装和配置(windowns||centos)
  10. Qt Designer设计 UI 文件并调用
  11. dp hp oracle 备份软件_HPDP备份软件设置
  12. Linux——安装英伟达Nvidia驱动
  13. 国产三极管与进口三极管的区别有哪些
  14. EOJ 1864 二分图匹配
  15. 鸿蒙生死印作用,逆天邪神:南溟神帝要抢鸿蒙生死印已成事实,但他还有更大作用...
  16. python的print输出格式举例_python中print输出格式是什么
  17. 了解Wi-fi频段概念
  18. 在计算机网络中ln代表的是,数学中e和ln的关系?
  19. 【C++】(十五)自定义数据类型——共用体类型、枚举类型
  20. 二进制视频数据常见标志位

热门文章

  1. r导入excel数据 linux,R语言中使用rio读取xlsx格式Excel文件|多个sheet表格|tidyverse rbind XLConnect readxl...
  2. iOS中UIControl的介绍
  3. Python求解非线性方程
  4. 全国大学生大数据技能竞赛(Hadoop集群搭建)
  5. trs java_trs常见问题 - This Is A FineDay - BlogJava
  6. 计算机培训感想幼儿园,幼儿园指南培训心得感想
  7. 奇点临近:人类文明延续
  8. 华为OD机试用Python实现 -【字母组合】(2023-Q1 新题)
  9. 【时间与空间】惯性系与地固系之间的转换
  10. Python期末总结