昨晚在脑内推导了一晚上的概率公式,没推导出来,今早师姐三言两语说用K-Means解决,太桑心了,昨晚一晚上没睡好。
小笨鸟要努力啊,K-Means,最简单的聚类算法,好好实现一下。
思路:
共有M个样本,设定K值作为样本的聚类个数(K值的设定很讲究,我还没去研究)。
随机产生K个点作为初始的 类核心。
do{
计算M个样本与K个类核心的距离,取距离最小的类核心为该样本的 类别。
聚一次结束后,根据每个类的样本,计算 聚类的 新 类核心。
}while(所有的类核心都没有变化,即该系统已经达到稳态,在继续循环下去也是同样的结果);
疑问:
收敛条件,是否能够设定为所有样本距离其类核心的距离和不在变小?
实现代码:
1 #include <stdio.h> 2 #include <time.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <string.h> 6 #include <limits.h> 7 8 typedef struct Node{ 9 double x; 10 double y; 11 int group; 12 }Node; 13 #define NodeNum 50 14 #define k 10 15 16 int main(){ 17 FILE* f = fopen("in.txt","w+"); 18 FILE* f2 = fopen("out.txt","w+"); 19 srand((int)time(0)); 20 Node node[NodeNum]; 21 for(int i = 0 ; i < NodeNum ; i++){ 22 node[i].x = 1+(int)(20.0*rand()/(RAND_MAX+1.0)); 23 node[i].y = 1+(int)(20.0*rand()/(RAND_MAX+1.0)); 24 } 25 for(int i = 0 ; i < NodeNum ; i++){ 26 printf("x = %.1lf , y = %.1lf ",node[i].x , node[i].y); 27 fprintf(f,"%.1lf %.1lf ",node[i].x , node[i].y); 28 } 29 30 Node circle[k]; 31 for(int i = 0 ; i < k ; i++){ 32 circle[i].x = 1+(int)(20.0*rand()/(RAND_MAX+1.0)); 33 circle[i].y = 1+(int)(20.0*rand()/(RAND_MAX+1.0)); 34 } 35 for(int i = 0 ; i < k ; i++){ 36 printf("circle X= %.1lf , circle Y = %.1lf ",circle[i].x , circle[i].y); 37 fprintf(f,"%.1lf %.1lf ",circle[i].x , circle[i].y); 38 } 39 40 int times = 0; 41 bool change = false; 42 do{ 43 double sumDis = 0; 44 for(int i = 0 ; i < NodeNum ; i++){ 45 double minDis = INT_MAX; 46 for(int j = 0 ; j < k ; j++){ 47 double curDis = pow((double)abs(node[i].x - circle[j].x),2) + 48 pow((double)abs(node[i].y - circle[j].y),2); 49 if(curDis < minDis){ 50 minDis = curDis; 51 node[i].group = j; 52 } 53 } 54 sumDis += minDis; 55 } 56 57 int newX[k] = {0},newY[k] = {0}; 58 for(int j = 0 ; j < k ; j++){ 59 int tempX = 0 , tempY = 0 ,count = 0; 60 for(int i = 0 ; i < NodeNum ; i++){ 61 if(node[i].group == j){ 62 count++; 63 tempX += node[i].x; 64 tempY += node[i].y; 65 } 66 } 67 newX[j] = tempX * 1.0 / count; 68 newY[j] = tempY * 1.0 / count; 69 } 70 change = false; 71 for(int i = 0 ; i < k ; i++){ 72 if(abs(circle[i].x - newX[i]) > 0.00001 || abs(circle[i].y - newY[i]) > 0.00001 ){ 73 change = true; 74 break; 75 } 76 } 77 if(change){ 78 for(int i = 0 ; i < k ; i++){ 79 circle[i].x = newX[i]; 80 circle[i].y = newY[i]; 81 } 82 } 83 printf("times = %d ************************* sumDis = %.5lf " , times++ , sumDis); 84 /*for(int i = 0 ; i < NodeNum ; i++){ 85 printf("x = %.1lf , y = %.1lf , group = %d ",node[i].x , node[i].y , node[i].group); 86 fprintf(f2,"%.1lf %.1lf %d ",node[i].x , node[i].y , node[i].group); 87 }*/ 88 for(int m = 0 ; m < k ; m++){ 89 printf("circle X = %.1f , circle Y = %.1f ",circle[m].x , circle[m].y); 90 fprintf(f2,"%.1lf %.1lf ",circle[m].x , circle[m].y); 91 } 92 }while(change); 93 94 95 return 0; 96 }