K-means算法介绍及C++语言实现


K-MEANS算法是输入聚类个数k,以及包含 n个数据对象的数据库,输出满足方差最小标准的k个聚类。
</pre>
基本简介k-means

算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。

k-means 算法基本步骤(1)

从 n个数据对象任意选择 k 个对象作为初始聚类中心;(2) 根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;(3) 重新计算每个(有变化)聚类的均值(中心对象);(4) 计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止;如果条件不满足则回到步骤(2)。

K-means算法C++实现过程示例
<span style="font-size:14px;">#include <iostream></span>

#include <math>
#include <vector>
#define k 5
using namespace std;
<span style="font-size:14px;">//计算两元组的欧式距离
float getDist(Element e1,Element e2)
{
	float dist=sqrt((e1.x-e2.x)*(e1.x-e2.x)+(e1.y-e2.y)*(e1.y-e2.y));
	return dist;
}
// 根据质心,决定当前元组属于哪个簇
int clusterOfElement(Element means[],Element elem)
{
	float dist=getDist(means[0],elem);
	float tmp;
	int label=0;
	for(int i=1;i<k;i++)
	{
		tmp=getDist(means[i],elem);
		if(tmp<dist){dist=tmp;label=i;}
	}
	return label;
}
//获得给定簇的平方误差
float getVar(vector<Element> cluster[],Element means[])
{
	float var=0;
	for(int i=0;i<k;i++)
	{
		vector<Element> elem=cluster[i];
		for(int j=0;j<elem.size();j++)
		{
			var+=getDist(elem[j],means[i]);
		}
	}
	return var;
}
//获得当前簇的质心
Element getMeans(vector<Element> cluster)
{
	int num=cluster.size();
	double meansX=0,meansY=0;
	Element elem;
	for(int i=0;i<num;i++)
	{
		meansX+=cluster[i].x;
		meansY+=cluster[i].y;
	}
	elem.x=meansX/num;
	elem.y=meansY/num;
	return elem;
}</span>
//聚类过程
void KMeans(vector<Element> elems ,vector<Element> clusters[k],Element means[k] )
{
	//vector<Element> clusters[k];
	//Element means[k];
	int i=0;
	//默认一开始将前K个元组的值作为k个簇的质心(均值)
	for(i=0;i<k;i++)
	{
		means[i].x=elems[i].x;
		means[i].y=elems[i].y;
	}
	int lable=0;  
    //根据默认的质心给簇赋值  
    for(i=0;i!=elems.size();++i)
	{  
        lable=clusterOfElement(means,elems[i]);  
        clusters[lable].push_back(elems[i]);  
    }  
	输出刚开始的簇  
    //for(lable=0;lable<3;lable++)
	//{  
    //   cout<<"第"<<lable+1<<"个簇:"<<endl;  
    //   vector<Element> t = clusters[lable];  
    //   for (i = 0; i< t.size(); i++)  
    //   {  
	//		cout<<"("<<t[i].x<<","<<t[i].y<<")"<<"   ";  
    //    }     
    //    cout<<endl;  
    // }  
	float oldVar=-1;
	float newVar=getVar(clusters,means);
	while(abs(newVar-oldVar)>=0.1)
	{
		 for (i = 0; i < k; i++) //更新每个簇的中心点  
        {  
            means[i] = getMeans(clusters[i]);  

        }  
        oldVar = newVar;  
        newVar = getVar(clusters,means); //计算新的准则函数值  
        for (i = 0; i < k; i++) //清空每个簇  
        {  
            clusters[i].clear();  
        }  
        //根据新的质心获得新的簇  
        for(i=0;i!=elems.size();++i){  
            lable=clusterOfElement(means,elems[i]);  
            clusters[lable].push_back(elems[i]);  
        }  
	}	
}
//获取距离k个质心距离最近的点的索引
int  getIndex(vector<Element> clusters,Element means)
{
	//getDist(Element e1,Element e2)
	int index=clusters.at(0).index;
	float temp=getDist(means,clusters.at(0));
	for(int i=0;i<clusters.size();i++)
	{
		if(getDist(means,clusters.at(i))<temp)
		{
			temp=getDist(means,clusters.at(i));
			index=clusters.at(i).index;
		}
	}
	return index;
}

void main()
{
vector<Element> data;
Element ele;
for(int i=0;i<keypoints.size();i++) //keypoints为预先定义的容器,已赋值(本文省略)
	{
		ele.index=i;
		ele.x=keypoints.at(i).x;
		ele.y=keypoints.at(i).y;		
		data.push_back(ele);		
	}
vector<Element> clusters[k];
	Element means[k];
	KMeans(data,clusters,means);
<span style="white-space:pre">	</span>FILE *kmeans=fopen("kmeans.txt","w");// 输出K个簇中的数据
	for(int i=0;i<k;i++)		
	{
		//cout<<means[i].x<<"   "<<means[i].y<<endl;
		fprintf(kmeans,"第%d簇\n",i);
		for(int j=0;j<clusters[i].size();j++)
		{
			fprintf(kmeans,"%.3f	%.3f \n",clusters[i].at(j).x,clusters[i].at(j).y);
		}
	}
	fclose(kmeans);
}


                
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值