k-means聚类算法是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,然后随机选取K个对象作为初始的聚类中心;计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心;聚类中心以及分配给它们的对象就代表一个聚类;每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
k-means聚类算法在市场分析、图像处理、模式识别、数据挖掘等多个领域中都有广泛应用。通过对数据进行聚类,可以发现数据集中的隐藏结构和规律,进而为决策提供有力支持。以下是一个简单的C++实现,展示了如何使用k-means算法对二维数据进行聚类。请注意,为了简单起见,此实现省略了一些优化和错误处理,但足以说明k-means算法的基本思想。代码如下。
#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <limits>
#include <algorithm>
struct Point {
double x, y;
};
double euclideanDistance(const Point& a, const Point& b) {
return std::sqrt(std::pow(a.x - b.x, 2) + std::pow(a.y - b.y, 2));
}
Point calculateCentroid(const std::vector<Point>& cluster) {
double sumX = 0, sumY = 0;
for (const auto& point : cluster) {
sumX += point.x;
sumY += point.y;
}
return {sumX / cluster.size(), sumY / cluster.size()};
}
std::vector<Point> initializeCentroids(const std::vector<Point>& data, int k) {
std::vector<Point> centroids(k);
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, data.size() - 1);
for (int i = 0; i < k; ++i) {
centroids[i] = data[dis(gen)];
}
return centroids;
}
std::vector<std::vector<Point>> kMeans(const std::vector<Point>& data, int k, int maxIterations) {
std::vector<Point> centroids = initializeCentroids(data, k);
std::vector<std::vector<Point>> clusters(k);
for (int iter = 0; iter < maxIterations; ++iter) {
// Assign points to clusters
std::fill(clusters.begin(), clusters.end(), std::vector<Point>());
for (const auto& point : data) {
int minIndex = -1;
double minDist = std::numeric_limits<double>::max();
for (int i = 0; i < k; ++i) {
double dist = euclideanDistance(point, centroids[i]);
if (dist < minDist) {
minDist = dist;
minIndex = i;
}
}
clusters[minIndex].push_back(point);
}
// Calculate new centroids
bool hasConverged = true;
for (int i = 0; i < k; ++i) {
Point oldCentroid = centroids[i];
centroids[i] = calculateCentroid(clusters[i]);
if (euclideanDistance(oldCentroid, centroids[i]) > std::numeric_limits<double>::epsilon()) {
hasConverged = false;
}
}
if (hasConverged) {
break;
}
}
return clusters;
}
int main() {
// Sample data points
std::vector<Point> data = {{1, 2}, {5, 8}, {1.5, 1.8}, {8, 8}, {1, 0.6}, {9, 11}};
// Number of clusters and maximum iterations
int k = 2;
int maxIterations = 100;
// Perform k-means clustering
std::vector<std::vector<Point>> clusters = kMeans(data, k, maxIterations);
// Print results
std::cout << "Clusters:" << std::endl;
for (int i = 0; i < clusters.size(); ++i) {
std::cout << "Cluster " << i + 1 << ":" << std::endl;
for (const auto& point : clusters[i]) {
std::cout << "(" << point.x << ", " << point.y << ")" << std::endl;
}
std::cout << std::endl;
}
// Optionally, print centroids
std::cout << "Centroids:" << std::endl;
for (const auto& centroid : kMeans(data, k, maxIterations)[0]) {
std::cout << "(" << centroid.x << ", " << centroid.y << ")" << std::endl;
}
return 0;
}
以上代码首先定义了一个`Point`结构体用于表示二维空间中的点,然后定义了几个辅助函数,包括计算欧几里得距离、计算聚类中心、初始化聚类中心等。`kMeans`函数实现了k-means算法的主要逻辑,包括分配点到聚类中以及重新计算聚类中心。`main`函数中创建了一些样本数据点,然后调用`kMeans`函数进行聚类,并打印出每个聚类中的点以及聚类中心。
注意:在实际应用中,k-means算法可能需要更多的优化,例如使用更高效的初始化方法(如k-means++),处理空聚类,以及利用并行计算加速算法等。此外,对于大规模数据集或高维数据,可能需要使用更高级的聚类算法。此示例仅用于展示k-means算法的基本实现。
标签:std,means,int,模型,vector,聚类,clusters From: https://blog.csdn.net/winterling/article/details/139521789