模糊C均值聚类(FCM,Fuzzy C Means)算法是基于模糊理论的一种软聚类算法。相对于K-Means算法的硬聚类,FCM提供了更加灵活的聚类结果。在很多情况下,数据集中的对象不能划分成为明显分离的簇,这时使用K-Means为每一个对象指定一个特定的簇,就可能出现问题。FCM定义了隶属度的概念,用于衡量某个对象对各个簇的隶属程度。因此,在模糊的数据集中使用FCM算法可以得到更好的结果。
一、算法流程图:
二、关键步骤的计算
聚类损失函数:
其中 Xj 为聚类的数据点,Zi为聚类中心。
隶属度计算函数:
对于单个样本,它对各个簇的隶属度之和等于1。
聚类中心更新函数:
迭代终止条件:
其中k是迭代步数, 是误差阈值。上式含义是,继续迭代下去,隶属程度也不会发生较大的变化。即认为隶属度不变了,已经达到比较优(局部最优或全局最优)状态了其中k是迭代步数, 是误差阈值。上式含义是,继续迭代下去,隶属程度也不会发生较大的变化。即认为隶属度不变了,已经达到比较优(局部最优或全局最优)状态了。
三、C++代码
/*
* data中存储了待聚类数据,代码中data为一维数组,可根据需要改为多维数组;
* size是data的大小;
* centerNum是聚类中心的数量;
* u是隶属度矩阵,由外部代码传入指针便于在外部访问。
*/
int* FCM(int size, int* data, int centerNum ,double** u) {
if (centerNum < 2) { //当聚类中心数小于2时,不需要进行聚类
return NULL;
}
for (int i = 0; i < centerNum; i++) {
u[i] = new double[size+ 1]{ 0 };
}
int* center = new int[centerNum]; //聚类中心
for (int i = 0; i < centerNum; i++)
center[i] = ((double)(i + 1) / (double)(centerNum + 1)) * size;
int count = 0;
while (count < 10) {//终止条件可根据数据特点设置
for (int i = 1; i <= size; i++) {
for (int j = 0; j < centerNum; j++) {
double ud = 0;
for (int k = 0; k < centerNum; k++) {
ud += pow(((double)abs(i - center[j]) / (double)abs(i - center[k])), 2);
}
u[j][i] = 1.0 / ud;
cout << "u " << j << "," << i << " :" << u[j][i] << endl;
}
}
for (int i = 0; i < centerNum; i++) {
unsigned long a = 0;
unsigned long b = 0;
for (int j = 1; j <= size; j++) {
a = a + (unsigned long)(u[i][j] * (double)data[j]);
b = b + (unsigned long)(u[i][j] * (double)j * (double)data[j]);
}
center[i] = (int)(b / a);
}
count++;
}
return center;
}