k-means算法
算法
先随机选取K个对象作为初始的聚类中心。然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。一旦全部对象都被分配了,每个聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是以下任何一个:
1、没有(或最小数目)对象被重新分配给不同的聚类。
2、没有(或最小数目)聚类中心再发生变化。
3、误差平方和局部最小。
性质
k均值聚类是使用最大期望算法(Expectation-Maximization algorithm)求解的高斯混合模型(Gaussian Mixture Model, GMM)在正态分布的协方差为单位矩阵,且隐变量的后验分布为一组狄拉克δ函数时所得到的特例。
算法步骤
输入:样本集D,簇的数目k,最大迭代次数N;
输出:簇划分(k个簇,使平方误差最小);
算法步骤:
(1)为每个聚类选择一个初始聚类中心;
(2)将样本集按照最小距离原则分配到最邻近聚类;
(3)使用每个聚类的样本均值更新聚类中心;
(4)重复步骤(2)、(3),直到聚类中心不再发生变化;
(5)输出最终的聚类中心和k个簇划分;
流程图
优缺点
优点
1、原理比较简单,实现也是很容易,收敛速度快。
2、当结果簇是密集的,而簇与簇之间区别明显时, 它的效果较好。
缺点
1、K值需要预先给定。
2、开局不同的中心点 对结果影响很大。
3、对噪音和异常点比较的敏感。
4、采用迭代方法,可能只能得到局部的最优解,而无法得到全局的最优解。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<math.h>
#define DIMENSIOM 2 //目前只是处理2维的数据
#define MAX_ROUND_TIME 100 //最大的聚类次数
typedef struct Item{
int dimension_1; //用于存放第一维的数据
int dimension_2; //用于存放第二维的数据
int clusterID; //用于存放该item的cluster center是谁
}Item;
Item* data;
typedef struct ClusterCenter{
double dimension_1;
double dimension_2;
int clusterID;
}ClusterCenter;
ClusterCenter* cluster_center_new;
int isContinue;
int* cluster_center; //记录center
double* distanceFromCenter; //记录一个“点”到所有center的距离
int data_size;
char filename[200];
int cluster_count;
void initial();
void readDataFromFile();
void initial_cluster();
void calculateDistance_ToOneCenter(int itemID, int centerID, int count);
void calculateDistance_ToAllCenter(int itemID);
void partition_forOneItem(int itemID);
void partition_forAllItem_OneCluster(int round);
void calculate_clusterCenter(int round);
void K_means();
void writeClusterDataToFile(int round);
void writeClusterCenterToFile(int round);
void compareNew_OldClusterCenter(double* new_