当前位置:首页 > C++ > 正文

C++聚类算法实战指南(从零开始实现K均值聚类)

在机器学习和数据挖掘领域,聚类算法是一种无监督学习方法,用于将相似的数据点分组。其中,K均值聚类(K-Means Clustering)是最经典、最常用的聚类算法之一。本教程将手把手教你使用C++语言从零实现一个完整的K均值聚类算法,即使你是编程小白,也能轻松上手!

C++聚类算法实战指南(从零开始实现K均值聚类) C++聚类算法 C++机器学习 聚类算法实现 K均值聚类C++ 第1张

什么是K均值聚类?

K均值聚类的目标是将 n 个数据点划分为 k 个簇(cluster),使得每个数据点属于离它最近的簇中心(质心)。算法通过迭代优化簇中心位置,直到收敛。

核心步骤如下:

  1. 随机选择 k 个初始质心;
  2. 将每个数据点分配给最近的质心;
  3. 重新计算每个簇的质心(即该簇所有点的平均值);
  4. 重复步骤2和3,直到质心不再显著变化或达到最大迭代次数。

准备工作:C++环境与依赖

我们只需要标准C++库(C++11或更高版本),无需额外依赖。确保你的编译器支持 vectorcmathiomanip 等头文件。

完整C++代码实现

下面是一个完整的、可运行的K均值聚类C++实现:

#include <iostream>#include <vector>#include <cmath>#include <cstdlib>#include <ctime>#include <iomanip>using namespace std;// 定义二维点结构class Point {public:    double x, y;    int cluster;    Point(double x = 0, double y = 0) : x(x), y(y), cluster(-1) {}    // 计算到另一个点的欧氏距离    double distance(const Point& p) const {        return sqrt(pow(x - p.x, 2) + pow(y - p.y, 2));    }};// K均值聚类主类class KMeans {private:    vector<Point> points;    vector<Point> centroids;    int k;    int maxIterations;public:    KMeans(vector<Point> data, int k, int maxIter = 100)        : points(data), k(k), maxIterations(maxIter) {        srand(time(0)); // 初始化随机种子        initializeCentroids();    }    void initializeCentroids() {        centroids.clear();        for (int i = 0; i < k; ++i) {            int idx = rand() % points.size();            centroids.push_back(points[idx]);        }    }    void assignClusters() {        for (auto& p : points) {            double minDist = numeric_limits<double>::max();            int closestCluster = 0;            for (int i = 0; i < k; ++i) {                double dist = p.distance(centroids[i]);                if (dist < minDist) {                    minDist = dist;                    closestCluster = i;                }            }            p.cluster = closestCluster;        }    }    void updateCentroids() {        vector<Point> newCentroids(k, Point(0, 0));        vector<int> counts(k, 0);        for (const auto& p : points) {            newCentroids[p.cluster].x += p.x;            newCentroids[p.cluster].y += p.y;            counts[p.cluster]++;        }        for (int i = 0; i < k; ++i) {            if (counts[i] > 0) {                newCentroids[i].x /= counts[i];                newCentroids[i].y /= counts[i];            }            centroids[i] = newCentroids[i];        }    }    void run() {        for (int iter = 0; iter < maxIterations; ++iter) {            assignClusters();            updateCentroids();        }    }    void printResults() {        cout << fixed << setprecision(2);        for (int i = 0; i < k; ++i) {            cout << "Cluster " << i << " centroid: ("                 << centroids[i].x << ", " << centroids[i].y << ")\n";        }        cout << "\nData point assignments:\n";        for (size_t i = 0; i < points.size(); ++i) {            cout << "Point (" << points[i].x << ", " << points[i].y                 << ") → Cluster " << points[i].cluster << "\n";        }    }};// 主函数:演示用法int main() {    // 示例数据:10个二维点    vector<Point> data = {        {1.0, 2.0}, {1.5, 1.8}, {5.0, 8.0}, {8.0, 8.0},        {1.0, 0.6}, {9.0, 11.0}, {8.0, 2.0}, {10.0, 2.0},        {9.0, 3.0}, {7.0, 2.0}    };    int k = 3; // 聚成3类    KMeans kmeans(data, k);    kmeans.run();    kmeans.printResults();    return 0;}

代码解析

  • Point 类:表示一个二维数据点,包含坐标 (x, y) 和所属簇编号。
  • KMeans 类:封装了整个聚类逻辑,包括初始化质心、分配簇、更新质心等。
  • 欧氏距离:用于衡量两个点之间的距离,是K均值算法的核心度量方式。
  • 随机初始化:使用 srand(time(0)) 确保每次运行结果略有不同(实际应用中可考虑更稳定的初始化策略如K-Means++)。

如何编译与运行?

将上述代码保存为 kmeans.cpp,然后在终端执行:

g++ -std=c++11 kmeans.cpp -o kmeans./kmeans

你将看到每个簇的质心坐标以及每个数据点被分配到的簇编号。

扩展与优化建议

这个基础实现适合学习理解。在实际项目中,你可以考虑:

  • 使用 K-Means++ 初始化质心,提高收敛速度和稳定性;
  • 支持高维数据(修改 Point 类为 vector);
  • 添加 SSE(误差平方和)评估指标;
  • 集成到更大的 C++机器学习 框架中。

总结

通过本教程,你已经掌握了如何用 C++聚类算法 实现经典的K均值聚类。这不仅加深了你对无监督学习的理解,也为后续开发更复杂的 聚类算法实现 打下了坚实基础。记住,实践是最好的老师——尝试修改数据集、调整k值,观察结果变化吧!

关键词回顾:C++聚类算法、C++机器学习、聚类算法实现、K均值聚类C++