一、K-Means算法思想
在数据集中,根据一定策略选择K个点作为每个簇的初始中心,然后观察剩余的数据,将数据划分到距离这K个点最近的簇中,也就是说将数据划分成K个簇完成一次划分,但形成的新簇并不一定是最好的划分,因此生成的新簇中,重新计算每个簇的中心点,然后在重新进行划分,直到每次划分的结果保持不变。在实际应用中往往经过很多次迭代仍然达不到每次划分结果保持不变,甚至因为数据的关系,根本就达不到这个终止条件,实际应用中往往采用变通的方法设置一个最大迭代次数,当达到最大迭代次数时,终止计算。
二、算法实现步骤
具体的算法步骤如下:
- 随机选择K个中心点
- 把每个数据点分配到离它最近的中心点;
- 重新计算每类中的点到该类中心点距离的平均值
- 分配每个数据到它最近的中心点;
- 重复步骤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;
}