昨晚在脑内推导了一晚上的概率公式,没推导出来,今早师姐三言两语说用K-Means解决,太桑心了,昨晚一晚上没睡好。
小笨鸟要努力啊,K-Means,最简单的聚类算法,好好实现一下。
思路:
共有M个样本,设定K值作为样本的聚类个数(K值的设定很讲究,我还没去研究)。
随机产生K个点作为初始的 类核心。
do{
计算M个样本与K个类核心的距离,取距离最小的类核心为该样本的 类别。
聚一次结束后,根据每个类的样本,计算 聚类的 新 类核心。
}while(所有的类核心都没有变化,即该系统已经达到稳态,在继续循环下去也是同样的结果);
疑问:
收敛条件,是否能够设定为所有样本距离其类核心的距离和不在变小?
实现代码:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <limits.h> typedef struct Node{
double x;
double y;
int group;
}Node;
#define NodeNum 50
#define k 10 int main(){
FILE* f = fopen("in.txt","w+");
FILE* f2 = fopen("out.txt","w+");
srand((int)time());
Node node[NodeNum];
for(int i = ; i < NodeNum ; i++){
node[i].x = +(int)(20.0*rand()/(RAND_MAX+1.0));
node[i].y = +(int)(20.0*rand()/(RAND_MAX+1.0));
}
for(int i = ; i < NodeNum ; i++){
printf("x = %.1lf , y = %.1lf\n",node[i].x , node[i].y);
fprintf(f,"%.1lf\t%.1lf\n",node[i].x , node[i].y);
} Node circle[k];
for(int i = ; i < k ; i++){
circle[i].x = +(int)(20.0*rand()/(RAND_MAX+1.0));
circle[i].y = +(int)(20.0*rand()/(RAND_MAX+1.0));
}
for(int i = ; i < k ; i++){
printf("circle X= %.1lf , circle Y = %.1lf\n",circle[i].x , circle[i].y);
fprintf(f,"%.1lf\t%.1lf\n",circle[i].x , circle[i].y);
} int times = ;
bool change = false;
do{
double sumDis = ;
for(int i = ; i < NodeNum ; i++){
double minDis = INT_MAX;
for(int j = ; j < k ; j++){
double curDis = pow((double)abs(node[i].x - circle[j].x),) +
pow((double)abs(node[i].y - circle[j].y),);
if(curDis < minDis){
minDis = curDis;
node[i].group = j;
}
}
sumDis += minDis;
} int newX[k] = {},newY[k] = {};
for(int j = ; j < k ; j++){
int tempX = , tempY = ,count = ;
for(int i = ; i < NodeNum ; i++){
if(node[i].group == j){
count++;
tempX += node[i].x;
tempY += node[i].y;
}
}
newX[j] = tempX * 1.0 / count;
newY[j] = tempY * 1.0 / count;
}
change = false;
for(int i = ; i < k ; i++){
if(abs(circle[i].x - newX[i]) > 0.00001 || abs(circle[i].y - newY[i]) > 0.00001 ){
change = true;
break;
}
}
if(change){
for(int i = ; i < k ; i++){
circle[i].x = newX[i];
circle[i].y = newY[i];
}
}
printf("times = %d \t ************************* sumDis = %.5lf \n" , times++ , sumDis);
/*for(int i = 0 ; i < NodeNum ; i++){
printf("x = %.1lf , y = %.1lf , group = %d \n",node[i].x , node[i].y , node[i].group);
fprintf(f2,"%.1lf\t%.1lf\t%d\n",node[i].x , node[i].y , node[i].group);
}*/
for(int m = ; m < k ; m++){
printf("circle X = %.1f , circle Y = %.1f\n",circle[m].x , circle[m].y);
fprintf(f2,"%.1lf\t%.1lf\n",circle[m].x , circle[m].y);
}
}while(change); return ;
}