找回密码
 立即注册
查看: 252|回复: 0

二维点数据kmeans算法聚类C++实现(可直接运行)

[复制链接]
发表于 2022-4-14 13:35 | 显示全部楼层 |阅读模式
转载自Wa_o_Fi
  1. #include<iostream>#include<vector>#include<math.h>#define k 2  //聚类数,可在kmeans算法处作参数usingnamespace std;struct Tuple  //数据结构{float attr1;//可看作xfloat attr2;//可看作y};floatDist(Tuple t1,Tuple t2)//欧式距离{returnsqrt((t1.attr1 - t2.attr1)*(t1.attr1 - t2.attr1)+(t1.attr2 - t2.attr2)*(t1.attr2 - t2.attr2));}//决定该样本属于哪一个聚类,传入的是聚类的质心(也是一个组,看作x,y)和一个样本,返回的是label;intclusterofTuple(Tuple means[],Tuple tuple){float distance =Dist(means[0],tuple);int label =0;for(int i =0; i < k; i++){if(Dist(means[i],tuple)<distance){
  2.                         label = i;}}return label;//找最近质心}//获得蔟集的平方误差,用来判断是否还需要继续迭代,传入的是蔟集的质心,以及所有归类好的样本,装着每个蔟集的容器数组,计算该聚类到自己质心的距离,所有距离的加和,返回所有的平方误差floatgetVar(Tuple means[],vector<Tuple> cluster[]){float var =0;for(int i =0; i < k; i++){
  3.                 vector<Tuple> t = cluster[i];for(int j =0; j < t.size(); j++){
  4.                         var +=Dist(means[i], t[j]);}}return var;}floatads(float oldvar,float newvar){//计算平方差变化float p;
  5.         p=newvar-oldvar;return p;}//计算当前蔟集的质心,输入的是一个蔟集的容器,质心的计算就是对于两个属性累加后除以个数求平均,然后返回质心,所以也要初始化一个质心Tuple t
  6. Tuple getMeans(vector<Tuple> cluster){
  7.         Tuple t;int num = cluster.size();float meanX =0, meanY =0;for(int i =0; i < num; i++){
  8.                 meanX += cluster[i].attr1;
  9.                 meanY += cluster[i].attr2;}
  10.         t.attr1 = meanX / num;
  11.         t.attr2 = meanY / num;return t;}voidKmeans(vector<Tuple> tuples)//kmeans算法{//定义与初始化//首先是要定义一个放置分好的蔟,那就是容器组咯,一个容器放一个蔟//然后还要有放k个质心的数组
  12.         vector<Tuple> cluster[k];//容器组
  13.         Tuple means[k];//放k个质心的数组//首先设置默认的质心,就是每个组分别是所有tuples里面最前面三个;for(int i =0; i < k; i++){
  14.                 means[i].attr1 = tuples[i].attr1;
  15.                 means[i].attr2 = tuples[i].attr2;}//第一次计算距离,进行分类,得到第一次的类标,容器的话是直接用push_back放置进去int label =0;for(int i =0; i < tuples.size(); i++){
  16.                 label =clusterofTuple(means, tuples[i]);
  17.                 cluster[label].push_back(tuples[i]);}//输出刚开始的蔟for(int i =0; i < k; i++){
  18.                 cout <<"the num of "<< i << endl;
  19.                 vector<Tuple> t = cluster[i];for(int j =0; j<t.size(); j++){
  20.                         cout << t[j].attr1 <<" "<< t[j].attr2 <<" "<< endl;}}float oldvar =0;//上一轮平方差float newvar =getVar(means,cluster);//循环迭代while(ads(oldvar,newvar)>10)//结束条件,可修改{//1先计算新的k个质心for(int i =0; i < k; i++){
  21.                                 means[i]=getMeans(cluster[i]);}//2清空分号蔟的容器,待会才可以根据新的质心重新分配for(int i =0; i < k; i++){
  22.                                 cluster[i].clear();}//3根据新的质心,对于原来传入的所有数据重新分配for(int i =0; i < tuples.size(); i++){
  23.                                 label =clusterofTuple(means, tuples[i]);
  24.                                 cluster[label].push_back(tuples[i]);}//4最后输出for(int i =0; i < k; i++){
  25.                                 vector<Tuple> t = cluster[i];for(int j =0; j < t.size(); j++){
  26.                                         cout << t[j].attr1 << t[j].attr2 << endl;}}}}
  27. vector<Tuple>input(vector<Tuple>&tuples){//数据输入,可改读入
  28.         Tuple tuple[3];
  29.         tuple[0].attr1=1;tuple[0].attr2=1;
  30.         tuple[1].attr1=1;tuple[1].attr2=2;
  31.         tuple[2].attr1=7;tuple[2].attr2=10;
  32.         tuples.push_back(tuple[0]);
  33.         tuples.push_back(tuple[1]);
  34.         tuples.push_back(tuple[2]);return tuples;}intmain(){
  35.     vector<Tuple> tuples;input(tuples);Kmeans(tuples);system("pause");return0;}
复制代码
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-6-1 04:27 , Processed in 1.119864 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表