K—Means算法实现
算法简介
K-MEANS算法是聚类算法中比较简单的一种,他是输入聚类个数k,以及包含 n个数据对象的数据库,输出满足方差最小标准k个聚类的一种算法。k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。
算法流程
输入:聚类个数k(这里的k=2),数据集。
输出:满足方差最小标准的k个聚类。
(1) 选择k个初始中心点;
(2) 对于每个对象,分别与每个中心点进行比较,假定与c差值最少,则该点为其中心点
(3) 对于所有标记为c点,重新计算c={ 所有标记为i的样本的每个特征的中心对象};
(4) 重复(2)(3),经过多次迭代,直到所有c值的变化小于给定阈值或者达到最大迭代次数。
代码实现
typedef struct
{
float x;
float y;
}Point;
int center[N]; /// 判断每个点属于哪个簇
Point p[N] = {
{1.0, 11.0},
{2.0, 56.0},
{8.0, 52.0},
{5.0, 20.0},
{7.0, 35.0},
{6.0, 24.0},
{1.0, 22.0},
{4.0, 39.0},
{7.0, 53.0},
{1.0, 43.0},
{3.0, 79.0}
};
Point mean[K]; /// 保存每个簇的中心点
//获得两点间直线距离
float getDistance(Point p1, Point p2)
{
float d;
d = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.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 += p[j].x;
tep.y += p[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[i].y);
}
}
/// 计算平方误差函数(x1-x2)^2+(y1-y2)^2 计算当前各点与当前所属中心点间距离误差
float getE()
{
int i, j;
float c = 0.0, sum = 0.0;
for(i = 0; i < K; ++i)
{
for(j = 0; j < N; ++j)
{
if(i == center[j])
{
c = (p[j].x - mean[i].x) * (p[j].x - mean[i].x) + (p[j].y - mean[i].y) * (p[j].y - mean[i].y);
sum += c;
}
}
}
return sum;
}
// 把N个点聚类
void clu()
{
int i, j, q;
float min;
float distance[N][K];
for(i = 0; i < N; ++i)
{
min = 100;
for(j = 0; j < K; ++j)//获得(point[i].x,point[i].y)的点到每个中心点的距离
{
distance[i][j] = getDistance(p[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 -%d\n", p[i].x, p[i].y, center[i] + 1);
}
printf("-----------------------------\n");
}