21xrx.com
2025-06-16 02:01:37 Monday
登录
文章检索 我的文章 写文章
Kmeans算法C++实现:简单易懂的机器学习聚类算法
2023-10-16 18:05:22 深夜i     22     0
Kmeans算法 C++实现 机器学习 聚类算法 简单易懂

K-means算法是一种非常常用的无监督学习算法,用于将一组数据点划分为K个相似的簇。它广泛应用于数据挖掘、图像分割、模式识别等领域。在本文中,我们将介绍如何使用C++实现简单易懂的K-means算法。

首先,让我们回顾一下K-means算法的基本原理。该算法的目标是将数据点分为K个簇,使得每个簇内的数据点尽可能相似,而不同簇之间的数据点尽可能不相似。算法的具体步骤如下:

1. 初始化K个聚类中心,可以随机选择数据集中的K个数据点作为初始中心。

2. 将每个数据点分配到与其最接近的聚类中心。

3. 更新聚类中心,将每个簇内的数据点的平均值作为新的聚类中心。

4. 重复第2步和第3步,直到聚类中心不再发生变化,或达到最大迭代次数。

现在让我们开始实现K-means算法的C++版本。

首先,我们需要定义一个数据结构来表示数据点。我们可以使用一个向量来表示数据点的各个特征值。

typedef vector<double> DataPoint;

然后,我们需要定义一个函数来计算两个数据点之间的距离。K-means算法通常使用欧氏距离来度量数据点之间的相似度。

double distance(const DataPoint& p1, const DataPoint& p2) {
  double sum = 0.0;
  for (int i = 0; i < p1.size(); ++i) {
    sum += pow(p1[i] - p2[i], 2);
  }
  return sqrt(sum);
}

接下来,我们可以开始实现K-means算法的主要功能函数。

vector<DataPoint> kmeans(const vector<DataPoint>& dataset, int K, int maxIter) {
  // 初始化聚类中心
  vector<DataPoint> centroids;
  random_device rd;
  mt19937 gen(rd());
  uniform_int_distribution<int> dis(0, dataset.size() - 1);
  for (int i = 0; i < K; ++i) {
    centroids.push_back(dataset[dis(gen)]);
  }
  vector<DataPoint> oldCentroids;
  int iter = 0;
  while (iter < maxIter) {
    oldCentroids = centroids;
    vector<vector<DataPoint>> clusters(K, vector<DataPoint>());
    // 将每个数据点分配到距离最近的聚类中心
    for (const auto& dataPoint : dataset) {
      int closestCentroid = 0;
      double closestDistance = numeric_limits<double>::max();
      for (int i = 0; i < K; ++i) {
        double dist = distance(dataPoint, centroids[i]);
        if (dist < closestDistance)
          closestCentroid = i;
          closestDistance = dist;
        
      }
      clusters[closestCentroid].push_back(dataPoint);
    }
    // 更新聚类中心
    for (int i = 0; i < K; ++i) {
      vector<double> sum(centroids[i].size(), 0.0);
      for (const auto& dataPoint : clusters[i]) {
        for (int j = 0; j < dataPoint.size(); ++j) {
          sum[j] += dataPoint[j];
        }
      }
      for (int j = 0; j < centroids[i].size(); ++j) {
        centroids[i][j] = sum[j] / clusters[i].size();
      }
    }
    // 检查聚类中心是否变化
    if (centroids == oldCentroids)
      break;
    
    ++iter;
  }
  return centroids;
}

最后,我们可以编写一个简单的主函数来测试我们的K-means算法。

int main() {
  vector<DataPoint> dataset = {
    1,
     4,
     2.5,
    1.5,
    3,
    4,
    4.5,
    5,
     5.5,
     3
  };
  int K = 2;
  int maxIter = 100;
  vector<DataPoint> centroids = kmeans(dataset, K, maxIter);
  for (int i = 0; i < K; ++i) {
    cout << "Cluster " << i + 1 << ": ";
    for (const auto& centroid : centroids[i])
      cout << centroid << " ";
    
    cout << endl;
  }
  return 0;
}

在上面的代码中,我们使用了一个简单的二维数据集,并将其分为两个簇。经过迭代,我们可以得到最终的聚类中心。输出结果类似于以下内容:

Cluster 1: 2.875 4.375
Cluster 2: 5.75 2.75

通过以上代码和解释,我们可以清楚地了解K-means算法的实现过程。使用C++实现K-means算法可以提供更高效和灵活的聚类功能,同时也增加了代码可读性和易懂性。

  
  

评论区