一道k-means算法的c++程序,帮帮看看哪里出了错

一道k-means算法的c++程序,帮帮看看哪里出了错,第1张

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])

}

}


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/12349975.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-22
下一篇2023-05-22

发表评论

登录后才能评论

评论列表(0条)

    保存