
K-means算法是很典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
k个初始类聚类中心点的选取对聚类结果具有较大的影响,因为在该算法第一步中是随机的选取任意k个对象作为初始聚类的中心,初始地代表一个簇。该算法在每次迭代中对数据集中剩余的每个对象,根据其与各个簇中心的距离将每个对象重新赋给最近的簇。当考察完所有数据对象后,一次迭代运算完成,新的聚类中心被计算出来。如果在一次迭代前后,J的值没有发生变化,说明算法已经收敛。
算法过程如下:
1)从N个文档随机选取K个文档作为质心
2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类
3)重新计算已经得到的各个类的质心
4)迭代2~3步直至新的质心与原质心相等或小于指雀弊乎定卜巧阈值,算法结束
具体如下:
输入:k, data[n]
(1) 选择k个初始中心点,例如c[0]=data[0],…c[k-1]=data[k-1];
(2) 对于data[0]….data[n],分别与c[0]…c[k-1]比较,假定与c[i]差值最少,就标记为i;顷悉
(3) 对于所有标记为i点,重新计算c[i]={ 所有标记为i的data[j]之和}/标记为i的个数;
(4) 重复(2)(3),直到所有c[i]值的变化小于给定阈值。
k-means算法本身不难,不过你截的图片看着太不方便了。
你的程序没什么问题啊?
写了一个,参考一下,有什么问题请说。#include<stdio.h>
#include<math.h>
int x[15][3]={{3,1,0},{3,2,0},{2,2,0},{3,3,0},{2,3,0},{8,8,0},{8,9,0},{9,8,0},{9,7,0},{9,9,0},{16,5,0},{16,4,0},{15,5,0},{15,6,0},{16,6,0}}
double oldcentral[3][3]//旧的中心点的坐标
double newcentral[3][3]//计算距离,分类后求平均值得到的新的中心点的坐标
int clas[15]//15个点各属于哪个类,类的编号从0开始
int clsno
int minDist(double x,double y,double z) //计算三个数的最小值,返回其序号。
{
if(x<=y&&x<=z)
return 0
if(y<x&&y<=z)
return 1
if(z<x&&z<y)
return 2
}
double distA(int i,int j)//计算两个点的距离,i和j分山码别是数组x和newcentral中的序号
{
double distx,disty,distz,dist
distx=(double)x[i][0]-(double)newcentral[j][0]
disty=(double)x[i][1]-(double)newcentral[j][1]
distz=(double)x[i][2]-(double)newcentral[j][2]
dist=sqrt(distx*distx+disty*disty+distz*distz)
return dist
}
void main()
{
int count[3]//记录每一类的个数;
int i,j
double dist[3]//求坐标点距离3个中心点距离时用到的变逗键哪量,
double cenL,cenLx,cenLy,cenLz//最后求新旧中心点距离的时候用到的变量
printf("The 15 points are:\n")//把所以点的坐标打印一遍,非必要语句
for(i=0i<15i++)
printf("%d %d %d \n",x[i][0],x[i][1],x[i][2])
for(i=0i<3i++)//新旧中心点赋初值。
for(j=0j<亮和3j++)
{
newcentral[i][j]=(double)x[i][j]
oldcentral[i][j]=-9999.0
}
for(i=0i<3i++)//头3个点作为初始的中心点。
{
clas[i]=i
cls[i]=i
}
while(1)//无限循环,退出条件是新旧中心点的距离小于0.005.
{
for(i=0i<3i++)//记录每一类的个数的数组赋初值
count[i]=0
for(i=0i<3i++)//新中心点的坐标拷贝到旧中心点数组中,因新中心点需重新计算。
for(j=0j<3j++)
oldcentral[i][j]=newcentral[i][j]
for(i=0i<15i++)//对15个点分别计算到中心点的距离。
{
for(j=0j<3j++)
dist[j]=distA(i,j)
clsno=minDist(dist[0],dist[1],dist[2])//求距离最小值,返回距离最小的对应中心点坐标。
clas[i]=clsno//将此点归到距离最小的那一类。
count[clsno]++
}
for(i=0i<3i++)//对新中心点坐标赋初值,进行下面的计算。
for(j=0j<3j++)
newcentral[i][j]=0.0
for(i=0i<15i++)//对每一类的坐标点计算其坐标之和。
for(j=0j<3j++)
newcentral[clas[i]][j]+=x[i][j]
for(i=0i<3i++)//坐标之和除以count数组元素,即得中心点坐标
for(j=0j<3j++)
newcentral[i][j]=newcentral[i][j]/count[i]
int flag=0//标志
for(i=0i<3i++)//求新旧中心点的距离
{
cenLx=newcentral[i][0]-oldcentral[i][0]
cenLy=newcentral[i][1]-oldcentral[i][1]
cenLz=newcentral[i][2]-oldcentral[i][2]
cenL=sqrt(cenLx*cenLx+cenLy*cenLy+cenLz*cenLz)
if(cenL>0.005)//只要有一个距离过大,表明未收敛,重新开始循环
flag=1
}
if(flag!=1)//只有当标志未被设置,退出while循环。
break
}
for(i=0i<15i++) //打印15个点各自所属的类。
{
printf("point %d(%d,%d,%d) belongs to class %d\n",i,x[i][0],x[i][1],x[i][2],clas[i])
}
}
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)