基于C++的K-means聚类算法实现
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)三个种类中的哪一类。
l 文件内容:
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
…
l 数据说明:
第一行表示分为三类,4个特征,150个数据后面依次为数据信息。
2. 输出数据—result.txt
输出数据输出实验数据聚类后的分类信息,与真实信息对比来分析程序聚类准确率。
l 文件内容:
0
2
0
1
0
…
l 数据说明:
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聚类算法实现相关推荐
- k means聚类算法_一文读懂K-means聚类算法
1.引言 什么是聚类?我们通常说,机器学习任务可以分为两类,一类是监督学习,一类是无监督学习.监督学习:训练集有明确标签,监督学习就是寻找问题(又称输入.特征.自变量)与标签(又称输出.目标.因变量) ...
- k means聚类算法_K-Means 聚类算法 20210108
说到聚类,应先理解聚类和分类的区别 聚类和分类最大的不同在于:分类的目标是事先已知的,而聚类则不一样,聚类事先不知道目标变量是什么,类别没有像分类那样被预先定义出来. K-Means 聚类算法有很多种 ...
- OpenCV官方文档 理解k - means聚类
理解k - means聚类 目标 在这一章中,我们将了解k - means聚类的概念,它是如何工作等. 理论 我们将这个处理是常用的一个例子. t恤尺寸问题 考虑一个公司要发布一个新模型的t恤. 显然 ...
- k均值聚类算法(K Means)及其实战案例
算法说明 K均值聚类算法其实就是根据距离来看属性,近朱者赤近墨者黑.其中K表示要聚类的数量,就是说样本要被划分成几个类别.而均值则是因为需要求得每个类别的中心点,比如一维样本的中心点一般就是求这些样本 ...
- OpenCV的k - means聚类 -对图片进行颜色量化
OpenCV的k - means聚类 目标 学习使用cv2.kmeans()数据聚类函数OpenCV 理解参数 输入参数 样品:它应该的np.float32数据类型,每个特性应该被放在一个单独的列. ...
- K-Means(K均值聚类算法)
K-Means(K均值聚类算法) 1.前言 要学习聚类算法就要知道聚类学习算法是什么,为什么要学习聚类学习聚类学习算法,有什么用途,下面就简单的做一下介绍,并且详细的说明k-means均值聚类学习算法 ...
- 基于Python的k均值聚类不同规格的商品名
基于Python的k均值聚类不同规格的商品名 前言 聚类的目标是使得同一簇内的点之间的距离较短,而不同簇中点之间的距离较大.以此来区分不同的群体. 本篇讲述使用k均值算法对超市购物记录集中的商品名称进 ...
- k均值聚类算法python_K均值和其他聚类算法:Python快速入门
k均值聚类算法python This post was originally published here 这篇文章最初发表在这里 Clustering is the grouping of obje ...
- python实现的基于NMF的多图聚类算法
python实现的基于NMF的多图聚类算法的封装 代码均由论文复现 文章目录 python实现的基于NMF的多图聚类算法的封装 前言 参考论文 一.NMF 二.Mjnmf 总结 前言 怕忘记干了这个事 ...
- K-means(K均值聚类算法)算法笔记
K-means(K均值聚类算法)算法笔记 K-means 算法,是比较简单的无监督的算法,通过设定好初始的类别k,然后不断循环迭代,将给定的数据自动分为K个类别.事实上,大家都知道K-means是怎么 ...
最新文章
- 这个假发太逼真!GAN帮你换发型,毫无违和感!
- Kubernetes面试题超详细总结
- 定时任务--mysql数据库备份
- win7系统安装信息服务器不可用怎么办,win7系统提示rpc服务器不可用怎么办
- 用FFmpeg搭建基于CNN的视频分析方案
- mips j指令_MIPS的基本实现
- Python3.1-标准库之Numpy
- 揭秘2019双11背后的云网络 – 双11网络架构和洛神系统
- mysql安装和配置(windowns||centos)
- Qt Designer设计 UI 文件并调用
- dp hp oracle 备份软件_HPDP备份软件设置
- Linux——安装英伟达Nvidia驱动
- 国产三极管与进口三极管的区别有哪些
- EOJ 1864 二分图匹配
- 鸿蒙生死印作用,逆天邪神:南溟神帝要抢鸿蒙生死印已成事实,但他还有更大作用...
- python的print输出格式举例_python中print输出格式是什么
- 了解Wi-fi频段概念
- 在计算机网络中ln代表的是,数学中e和ln的关系?
- 【C++】(十五)自定义数据类型——共用体类型、枚举类型
- 二进制视频数据常见标志位
热门文章
- r导入excel数据 linux,R语言中使用rio读取xlsx格式Excel文件|多个sheet表格|tidyverse rbind XLConnect readxl...
- iOS中UIControl的介绍
- Python求解非线性方程
- 全国大学生大数据技能竞赛(Hadoop集群搭建)
- trs java_trs常见问题 - This Is A FineDay - BlogJava
- 计算机培训感想幼儿园,幼儿园指南培训心得感想
- 奇点临近:人类文明延续
- 华为OD机试用Python实现 -【字母组合】(2023-Q1 新题)
- 【时间与空间】惯性系与地固系之间的转换
- Python期末总结