K-Means算法思想+简单代码案例(C语言)

一、K-Means算法思想

在数据集中根据一定策略选择K个点作为每个簇的初始中心,然后观察剩余的数据,将数据划分到距离这K个点最近的簇中,也就是说将数据划分成K个簇完成一次划分,但形成的新簇并不一定是最好的划分,因此生成的新簇中,重新计算每个簇的中心点,然后在重新进行划分,直到每次划分的结果保持不变。在实际应用中往往经过很多次迭代仍然达不到每次划分结果保持不变,甚至因为数据的关系,根本就达不到这个终止条件,实际应用中往往采用变通的方法设置一个最大迭代次数,当达到最大迭代次数时,终止计算。

二、算法实现步骤

具体的算法步骤如下:

  1. 随机选择K个中心点
  2. 把每个数据点分配到离它最近的中心点
  3. 重新计算每类中的点到该类中心点距离的平均值
  4. 分配每个数据到它最近的中心点
  5. 重复步骤3和4,直到所有的观测值不再被分配或是达到最大的迭代次数(R把10次作为默认迭代次数)。

代码实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
 
#define N 11
#define K 3
 
typedef struct
{
	float x;
	float y;
}Point;
 
int center[N];  //判断每个点属于哪个簇
 
Point point[N] = {
	{163.7, 58.2},
 	{173.0, 70.5},
 	{163.7, 45.1},
 	{150.9, 52.8},
 	{157.1, 50.3},
 	{157.3, 44.8},
 	{160.7, 52.2},
 	{147.6, 53.7},
 	{175.2, 68.0},
 	{155.3, 56.9},
 	{160.0, 49.0}  //以十一个同学的身高、体重作为收集的数据 
};
 
Point mean[K];  //保存每个簇的中心点
 
float getDistance(Point point1, Point point2)
{
 	float d;
 	d = sqrt((point1.x - point2.x) * (point1.x - point2.x) + (point1.y - point2.y) * (point1.y - point2.y));
 	return d;
}
 
//计算每个簇的中心点
void getMean(int center[N])
{
 	Point tep;
 	int i, j, count = 0;
 	for(i = 0; i < K; ++i)
 	{
  		count = 0;
  		tep.x = 0.0;   //每算出一个簇的中心点值后清0
  		tep.y = 0.0;
        
		for(j = 0; j < N; ++j)
  		{
   			if(i == center[j])
   			{
    			count++;
    			tep.x += point[j].x;
    			tep.y += point[j].y;
   			}
  		}
  		
		tep.x /= count;
  		tep.y /= count;
 	 	mean[i] = tep;
 	}
 	
 	for(i = 0; i < K; ++i)
 		printf("The new center point of%d is:\t(%f,%f)\n",i+1,mean[i].x,mean[j].y);
}

//计算平方误差函数
float getE()
{ 
	int i,j;
  	float cnt=0.0,sum=0.0;
  	for(i=0;i<K;++i)
  	{ 
    	for(j=0;j<N;++j)
    	{ 
	  		if(i==center[j])
      		{
      			cnt=(point[j].x-mean[i].x)*(point[j].x-mean[i].x)+(point[j].y-mean[i].y)*(point[j].y-mean[i].y);
      			sum+=cnt;
	  		}
		}
  	}
  return sum;
} 

//把N个结点聚类化
void cluster()
{
	int i,j,q;
	float min;
	float distance[N][K];
	for(i=0;i<N;++i)
	{
		min=999999.0;
		for(j=0;j<K;++j)
			distance[i][j]=getDistance(point[i],mean[j]);
		
		for(q=0;q<K;++q)
		{
			if(distance[i][q]<min)
			{
				min=distance[i][q];
				center[i]=q;
			}
		}
		printf("(%.0f,%.0f)\t in cluster-%d\n",point[i].x,point[i].y,center[i]+1);
	}
	printf("-------------------\n");
} 

int main()
{
	int i,j,n=0;
	float temp1;
	float temp2,t;
	printf("-----------Data sets----------\n");
	for(i=0;i<N;++i)
		printf("\t(%.0f,%.0f)\n",point[i].x,point[i].y);
	printf("--------------\n");
	
	mean[0].x=point[0].x;
	mean[0].y=point[0].y;
	mean[1].x=point[3].x;
	mean[1].y=point[3].y;
	mean[2].x=point[6].x;
	mean[2].y=point[6].y;
	
	cluster();
	temp1=getE();
	n++;
	printf("The E1 is:%f\n\n",temp1);
	getMean(center);
	
	cluster();
	temp2=getE();
	n++;
	printf("The E2 is:%f\n\n",temp2);
	
	while(fabs(temp2-temp1)!=0)
	{
		temp1=temp2;
		getMean(center);
		cluster();
		temp2=getE();
		n++;
		printf("The E%d is:%f\n",temp2);
	}
	
	printf("The total number of cluster is:%d\n\n",n);
	system("pause");
	return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值