点云 K-Means聚类算法 (附c++代码)

本文介绍了K-Means聚类算法的原理,包括算法步骤和基于C++的代码实现。K-Means通过迭代更新聚类中心,将点云数据分成具有明显差异的类别,但对噪声敏感,适合在数据预处理后使用。
摘要由CSDN通过智能技术生成

一、K-Means算法

在诸多的聚类方法中,K-Means聚类方法是属于“基于原型的聚类”(也称为原型聚类)的方法,此类方法均是假设聚类结构能通过一组原型刻画,在现实聚类中极为常用。通常情况下,该类算法会先对原型进行初始化,然后再对原型进行迭代更新求解。采用不同的原型表示、不同的求解方式,也将会产生不同的算法。

K-Means算法作为一种经典的“原型聚类”算法,其原型选择的是“K个聚类中心”,迭代求解的方式是以相邻两次求解的“质心”(同一类所有的点的x,y,z坐标的平均值)变化程度而进行的,这也可能就是K-Means聚类名字的由来:K个聚类中心+质心(坐标平均值)。

二、K-Means算法步骤

过程其实相对简单:

1、初始化原型,也就是指定K值和K个聚类中心。这其中聚类中心的指定可以人为的输入、也可以随机选择或者其他方式都可以,不过尽量保证聚类中心之间的距离不要选的太近。 2、聚类。遍历所有数据点,计算每个数据点到这K个聚类中心的距离(我这里选择的是欧式距离,也可以选择马氏距离或者其他距离),将每个数据点分配给距离该点最近的聚类中心所属的类别,直到最后一个数据点。 3、更新聚类中心。也就是计算每一类的质心,并将本次计算出的聚类中心与上一次的聚类中心进行比较

k-means聚类算法是一种常用的无监督学习算法,用于将数据集划分为k个不同的类别。它的主要思想是通过迭代的方式将数据点分配到k个簇中,使得每个数据点与所属簇的质心之间的距离最小化。 以下是k-means聚类算法C++实现步骤: 1. 初始化:随机选择k个数据点作为初始质心。 2. 分配:对于每个数据点,计算其与每个质心之间的距离,并将其分配到距离最近的质心所属的簇中。 3. 更新:对于每个簇,计算其所有数据点的平均值作为新的质心。 4. 重复步骤2和步骤3,直到质心不再发生变化或达到最大迭代次数。 以下是一个简单的k-means聚类算法C++代码示例: ```cpp #include <iostream> #include <vector> #include <cmath> // 计算两个数据点之间的欧氏距离 double distance(const std::vector<double>& point1, const std::vector<double>& point2) { double sum = 0.0; for (int i = 0; i < point1.size(); ++i) { sum += std::pow(point1[i] - point2[i], 2); } return std::sqrt(sum); } // k-means聚类算法 std::vector<int> kMeansClustering(const std::vector<std::vector<double>>& data, int k, int maxIterations) { std::vector<std::vector<double>> centroids(k); // 质心 std::vector<int> clusterAssignments(data.size()); // 数据点所属的簇 // 随机初始化质心 for (int i = 0; i < k; ++i) { centroids[i] = data[std::rand() % data.size()]; } bool centroidsChanged = true; int iterations = 0; while (centroidsChanged && iterations < maxIterations) { centroidsChanged = false; // 分配数据点到最近的质心所属的簇 for (int i = 0; i < data.size(); ++i) { double minDistance = std::numeric_limits<double>::max(); int minIndex = -1; for (int j = 0; j < k; ++j) { double dist = distance(data[i], centroids[j]); if (dist < minDistance) { minDistance = dist; minIndex = j; } } if (clusterAssignments[i] != minIndex) { clusterAssignments[i] = minIndex; centroidsChanged = true; } } // 更新质心 for (int i = 0; i < k; ++i) { std::vector<double> sum(data.size(), 0.0); int count = 0; for (int j = 0; j < data.size(); ++j) { if (clusterAssignments[j] == i) { for (int d = 0; d < data[j].size(); ++d) { sum[d] += data[j][d]; } count++; } } if (count > 0) { for (int d = 0; d < sum.size(); ++d) { centroids[i][d] = sum[d] / count; } } } iterations++; } return clusterAssignments; } int main() { // 示例数据 std::vector<std::vector<double>> data = {{1.0, 2.0}, {2.0, 1.0}, {10.0, 12.0}, {12.0, 10.0}, {20.0, 22.0}, {22.0, 20.0}}; int k = 2; // 聚类的簇数 int maxIterations = 100; // 最大迭代次数 std::vector<int> clusterAssignments = kMeansClustering(data, k, maxIterations); // 输出每个数据点所属的簇 for (int i = 0; i < clusterAssignments.size(); ++i) { std::cout << "Data point " << i << " belongs to cluster " << clusterAssignments[i] << std::endl; } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

点云-激光雷达-Slam-三维牙齿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值