聚类是无监督学习中一种常用的算法,用于将数据集中的对象分组(称为簇),使得同一簇中的对象相似度较高,而不同簇之间的对象相似度较低。在许多领域,如数据挖掘、图像处理和模式识别等,聚类算法都有广泛应用。
在本项目中,我们将实现最常见的聚类算法之一——K均值聚类(K-Means Clustering)。该算法的目标是通过迭代的方式将数据集划分为 K 个簇,每个簇由其中心(均值)表示。
输入参数:
K均值算法:
距离计算:
输出结果:
#include
#include
#include
#include
#include
struct Point {
double x, y;
int cluster; // 保存该点所属的簇编号
};
// 计算两点之间的欧几里得距离
double euclideanDistance(const Point& p1, const Point& p2) {
return std::sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
// K均值聚类算法
void kMeans(std::vector& points, int K) {
int n = points.size();
std::vector centroids(K); // 存储簇中心
std::vector pointCounts(K, 0); // 记录每个簇的点数
// 随机初始化K个簇中心
std::srand(std::time(0));
for (int i = 0; i < K; ++i) {
centroids[i] = points[std::rand() % n]; // 随机选取数据点作为簇中心
}
bool converged = false;
while (!converged) {
// 步骤1:为每个数据点分配簇
for (auto& point : points) {
double minDistance = std::numeric_limits::max();
int closestCluster = -1;
for (int i = 0; i < K; ++i) {
double dist = euclideanDistance(point, centroids[i]);
if (dist < minDistance) {
minDistance = dist;
closestCluster = i;
}
}
point.cluster = closestCluster;
}
// 步骤2:更新每个簇的中心
std::vector newCentroids(K, {0.0, 0.0});
std::fill(pointCounts.begin(), pointCounts.end(), 0); // 重置每个簇的点数
for (const auto& point : points) {
newCentroids[point.cluster].x += point.x;
newCentroids[point.cluster].y += point.y;
pointCounts[point.cluster]++;
}
// 计算新的簇中心
for (int i = 0; i < K; ++i) {
if (pointCounts[i] > 0) {
newCentroids[i].x /= pointCounts[i];
newCentroids[i].y /= pointCounts[i];
}
}
// 判断簇中心是否变化,如果没有变化则表示收敛
converged = true;
for (int i = 0; i < K; ++i) {
if (euclideanDistance(centroids[i], newCentroids[i]) > 1e-6) {
converged = false;
break;
}
}
centroids = newCentroids; // 更新簇中心
}
}
void printClusters(const std::vector& points) {
for (const auto& point : points) {
std::cout << "Point (" << point.x << ", " << point.y << ") is in cluster " << point.cluster << std::endl;
}
}
int main() {
// 测试数据:一组二维点
std::vector points = {
{1.0, 2.0, -1}, {1.5, 1.8, -1}, {5.0, 8.0, -1}, {8.0, 8.0, -1},
{1.0, 0.6, -1}, {9.0, 11.0, -1}, {8.0, 2.0, -1}, {10.0, 2.0, -1},
{9.0, 3.0, -1}, {7.0, 5.0, -1}
};
int K = 3; // 设置簇的数量
// 执行K均值聚类
kMeans(points, K);
// 输出聚类结果
printClusters(points);
return 0;
}
Point 结构体:
x
和 y
是数据点的坐标,cluster
是该点所属的簇编号。euclideanDistance 函数:
kMeans 函数:
printClusters 函数:
main 函数:
kMeans
函数来执行聚类,并通过 printClusters
函数输出聚类结果。通过本项目,我们实现了 K 均值聚类算法,并应用于二维数据点的聚类问题。算法通过随机初始化簇中心,然后通过迭代方式将数据点分配到簇中,并更新簇中心,直到簇中心收敛。最终,算法输出每个数据点所属的簇。
初始化优化:
高维数据支持:
性能优化:
并行化:
假设输入数据点如下:
Point (1, 2) is in cluster 0
Point (1.5, 1.8) is in cluster 0
Point (5, 8) is in cluster 1
Point (8, 8) is in cluster 1
Point (1, 0.6) is in cluster 0
Point (9, 11) is in cluster 2
Point (8, 2) is in cluster 1
Point (10, 2) is in cluster 1
Point (9, 3) is in cluster 1
Point (7, 5) is in cluster 1
这个输出表明,数据点被正确地分配到各自的簇中,簇编号从 0 到 2,分别表示不同的簇。