21xrx.com
2024-11-22 02:20:35 Friday
登录
文章检索 我的文章 写文章
Kmeans算法C++实现:简单易懂的机器学习聚类算法
2023-10-16 18:05:22 深夜i     --     --
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算法可以提供更高效和灵活的聚类功能,同时也增加了代码可读性和易懂性。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复