K-means算法
在使用K-means算法进行聚类时,我们通常需要执行以下步骤:
初始化簇中心、
分配样本点到最近的簇中心、
更新簇中心,直到收敛。
这些步骤可以用C++实现如下:
#include <iostream> #include <vector> #include <cmath> #include <limits> #include <cstdlib> #include <ctime> using namespace std; // 定义一个简单的点(数据样本) struct Point { double x, y; // 使用x和y表示点在二维空间中的位置 }; // 计算两个点之间的距离(欧氏距离) double computeDistance(const Point& a, const Point& b) { // 公式:sqrt((x1 - x2)^2 + (y1 - y2)^2) return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)); } // 初始化簇中心 vector<Point> initializeCentroids(const vector<Point>& points, int k) { vector<Point> centroids; srand(time(0)); // 利用当前时间作为随机种子,确保每次运行结果不同 for (int i = 0; i < k; ++i) { // 随机选择数据点作为初始的簇中心 centroids.push_back(points[rand() % points.size()]); } return centroids; } // 分配点到最近的簇中心 vector<int> assignClusters(const vector<Point>& points, const vector<Point>& centroids) { vector<int> assignments(points.size()); for (size_t i = 0; i < points.size(); ++i) { double minDistance = numeric_limits<double>::max(); // 初始化为最大值,用于找到最小距离 int bestCluster = 0; // 记录当前点所属的最佳簇 for (size_t j = 0; j < centroids.size(); ++j) { double distance = computeDistance(points[i], centroids[j]); if (distance < minDistance) { minDistance = distance; // 更新最小距离 bestCluster = j; // 更新最佳簇索引 } } assignments[i] = bestCluster; // 将点分配到最近的簇 } return assignments; } // 更新簇中心 vector<Point> updateCentroids(const vector<Point>& points, const vector<int>& assignments, int k) { vector<Point> newCentroids(k); // 存储新的簇中心 vector<int> count(k, 0); // 存储每个簇的点的数量 for (size_t i = 0; i < assignments.size(); ++i) { newCentroids[assignments[i]].x += points[i].x; newCentroids[assignments[i]].y += points[i].y; count[assignments[i]]++; // 增加簇中点的数量 } for (int i = 0; i < k; ++i) { if (count[i] != 0) { // 防止除以零 newCentroids[i].x /= count[i]; // 计算新簇中心的平均x newCentroids[i].y /= count[i]; // 计算新簇中心的平均y } } return newCentroids; } // K-means聚类算法 vector<int> kMeansClustering(const vector<Point>& points, int k, int maxIterations = 100) { vector<Point> centroids = initializeCentroids(points, k); // 初始化聚类中心 for (int it = 0; it < maxIterations; ++it) { vector<int> assignments = assignClusters(points, centroids); // 分配点到簇 vector<Point> newCentroids = updateCentroids(points, assignments, k); // 更新簇中心 // 检查是否已经收敛 if (newCentroids == centroids) // 如果新的簇中心没有变化,则算法收敛 break; centroids = newCentroids; // 更新簇中心为新簇中心 } return assignClusters(points, centroids); // 返回最终的簇分配 } int main() { vector<Point> points = {{1.0, 2.0}, {1.5, 1.8}, {5.0, 8.0}, {8.0, 8.0}, {1.0, 0.6}, {9.0, 11.0}}; int k = 2; // 选择将数据分为多少个簇 vector<int> result = kMeansClustering(points, k); for (size_t i = 0; i < result.size(); ++i) { cout << "Point (" << points[i].x << ", " << points[i].y << ") is in cluster " << result[i] << endl; } return 0; }