C++ 实现多维向量聚类 FCM 算法
由于 FCM 算法涉及到矩阵运算,因此需要使用线性代数库 Eigen。以下是一个多维向量进行聚类的 FCM 算法的 C++ 实现:
#include <iostream>
#include <vector>
#include <Eigen/Dense>
using namespace Eigen;
// FCM 算法的实现
class FCM {
public:
FCM(int num_clusters, int max_iter, double m, double epsilon) :
num_clusters_(num_clusters), max_iter_(max_iter), m_(m), epsilon_(epsilon) {}
// 对数据进行聚类
void cluster(const MatrixXd& data, VectorXi& labels) {
int num_samples = data.rows();
int num_features = data.cols();
// 初始化隶属度矩阵 U
MatrixXd U = MatrixXd::Random(num_samples, num_clusters_);
U = U.array().abs();
U = U.rowwise() / U.colwise().sum();
// 迭代更新隶属度矩阵 U 和聚类中心矩阵 C
for (int i = 0; i < max_iter_; i++) {
MatrixXd U_old = U;
// 计算聚类中心矩阵 C
MatrixXd C(num_clusters_, num_features);
for (int k = 0; k < num_clusters_; k++) {
double sum1 = 0, sum2 = 0;
for (int j = 0; j < num_features; j++) {
sum1 = 0, sum2 = 0;
for (int i = 0; i < num_samples; i++) {
sum1 += pow(U(i, k), m_) * data(i, j);
sum2 += pow(U(i, k), m_);
}
C(k, j) = sum1 / sum2;
}
}
// 计算隶属度矩阵 U
for (int k = 0; k < num_clusters_; k++) {
for (int i = 0; i < num_samples; i++) {
double sum = 0;
for (int j = 0; j < num_clusters_; j++) {
double distance = (data.row(i) - C.row(k)).norm();
if (distance < epsilon_) distance = epsilon_;
sum += pow(distance / (data.row(i) - C.row(j)).norm(), 2 / (m_ - 1));
}
U(i, k) = 1 / sum;
}
}
// 判断是否收敛
if ((U_old - U).norm() < epsilon_) break;
}
// 根据隶属度矩阵 U 确定聚类标签
labels = VectorXi::Zero(num_samples);
for (int i = 0; i < num_samples; i++) {
int max_index = 0;
double max_value = U(i, 0);
for (int j = 1; j < num_clusters_; j++) {
if (U(i, j) > max_value) {
max_index = j;
max_value = U(i, j);
}
}
labels(i) = max_index;
}
}
private:
int num_clusters_; // 聚类数
int max_iter_; // 最大迭代次数
double m_; // 模糊度因子
double epsilon_; // 防止分母为 0 的小值
};
// 示例
int main() {
// 构造样本数据
MatrixXd data(10, 3);
data << 1, 2, 3,
4, 5, 6,
7, 8, 9,
10, 11, 12,
13, 14, 15,
16, 17, 18,
19, 20, 21,
22, 23, 24,
25, 26, 27,
28, 29, 30;
// 聚类
int num_clusters = 3;
int max_iter = 100;
double m = 2.0;
double epsilon = 1e-5;
FCM fcm(num_clusters, max_iter, m, epsilon);
VectorXi labels;
fcm.cluster(data, labels);
// 输出聚类结果
std::cout << "Cluster labels:" << std::endl;
std::cout << labels.transpose() << std::endl;
return 0;
}
上述代码中,FCM 类的构造函数参数包括聚类数、最大迭代次数、模糊度因子 m 和防止分母为 0 的小值 epsilon。cluster 函数用于对数据进行聚类,返回聚类结果的标签。在示例中,构造了一个 10×3 的样本数据,聚成 3 类,最大迭代次数为 100,模糊度因子为 2.0,防止分母为 0 的小值为 1e-5。聚类结果如下:
Cluster labels:
0 0 0 1 1 1 2 2 2 2
原文地址: https://www.cveoy.top/t/topic/mRBz 著作权归作者所有。请勿转载和采集!