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

C语言聚类算法实战指南(手把手教你用C语言实现K均值聚类)

在机器学习和数据挖掘领域,C语言聚类算法是一个基础而重要的主题。虽然Python等高级语言在数据分析中更常见,但使用C语言实现聚类不仅能加深对算法原理的理解,还能提升程序性能。本教程将带你从零开始,用C语言实现经典的K均值聚类算法,即使你是编程小白也能轻松上手!

什么是聚类?

聚类是一种无监督学习方法,目的是将相似的数据点分组到同一类别(簇)中。K均值(K-means)是最常用的聚类算法之一,它通过迭代优化簇中心,使得每个数据点到其所属簇中心的距离最小。

C语言聚类算法实战指南(手把手教你用C语言实现K均值聚类) C语言聚类算法  K均值聚类实现 聚类分析C语言 机器学习C语言教程 第1张

K均值聚类算法步骤

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

C语言实现K均值聚类

下面我们用C语言一步步实现这个算法。我们将处理二维平面上的点(x, y),但代码结构很容易扩展到更高维度。

1. 定义数据结构

#include <stdio.h>#include <stdlib.h>#include <math.h>#define MAX_POINTS 100   // 最大数据点数#define MAX_DIM 2        // 数据维度(这里用2维)typedef struct {    double coords[MAX_DIM]; // 点的坐标    int cluster;            // 所属簇编号} Point;typedef struct {    double coords[MAX_DIM]; // 簇中心坐标    int count;              // 该簇包含的点数} Centroid;

2. 计算两点间欧氏距离

double distance(double *p1, double *p2, int dim) {    double sum = 0.0;    for (int i = 0; i < dim; i++) {        double diff = p1[i] - p2[i];        sum += diff * diff;    }    return sqrt(sum);}

3. 主要聚类函数

void kmeans(Point points[], int num_points, Centroid centroids[],             int k, int max_iters) {    int dim = MAX_DIM;    int changed;    // 初始化:所有点未分配簇    for (int i = 0; i < num_points; i++) {        points[i].cluster = -1;    }    for (int iter = 0; iter < max_iters; iter++) {        changed = 0;        // 步骤1:为每个点分配最近的簇        for (int i = 0; i < num_points; i++) {            int closest_cluster = 0;            double min_dist = distance(points[i].coords,                                       centroids[0].coords, dim);            for (int j = 1; j < k; j++) {                double dist = distance(points[i].coords,                                       centroids[j].coords, dim);                if (dist < min_dist) {                    min_dist = dist;                    closest_cluster = j;                }            }            if (points[i].cluster != closest_cluster) {                points[i].cluster = closest_cluster;                changed = 1;            }        }        // 如果没有点改变簇,提前结束        if (!changed) break;        // 步骤2:更新簇中心        for (int j = 0; j < k; j++) {            centroids[j].count = 0;            for (int d = 0; d < dim; d++) {                centroids[j].coords[d] = 0.0;            }        }        // 累加每个簇中的点坐标        for (int i = 0; i < num_points; i++) {            int cluster_id = points[i].cluster;            centroids[cluster_id].count++;            for (int d = 0; d < dim; d++) {                centroids[cluster_id].coords[d] += points[i].coords[d];            }        }        // 计算新的簇中心(平均值)        for (int j = 0; j < k; j++) {            if (centroids[j].count > 0) {                for (int d = 0; d < dim; d++) {                    centroids[j].coords[d] /= centroids[j].count;                }            }        }    }}

4. 主函数与测试数据

int main() {    // 测试数据:8个二维点    Point points[MAX_POINTS] = {        {{1.0, 1.0}}, {{1.5, 2.0}}, {{3.0, 4.0}}, {{5.0, 7.0}},        {{3.5, 5.0}}, {{4.5, 5.0}}, {{3.5, 4.5}}, {{2.0, 2.0}}    };    int num_points = 8;    int k = 2; // 分成2个簇    int max_iters = 100;    // 初始化簇中心(可随机选择,这里手动指定)    Centroid centroids[2] = {        {{1.0, 1.0}, 0},        {{5.0, 7.0}, 0}    };    // 执行K均值聚类    kmeans(points, num_points, centroids, k, max_iters);    // 输出结果    printf("聚类结果:\n");    for (int i = 0; i < num_points; i++) {        printf("点 (%.1f, %.1f) 属于簇 %d\n",                points[i].coords[0], points[i].coords[1],                points[i].cluster);    }    printf("\n最终簇中心:\n");    for (int j = 0; j < k; j++) {        printf("簇 %d 中心: (%.2f, %.2f)\n", j,                centroids[j].coords[0], centroids[j].coords[1]);    }    return 0;}

编译与运行

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

gcc -o kmeans kmeans.c -lm./kmeans

注意:链接数学库 -lm 是必须的,因为使用了 sqrt 函数。

总结

通过本教程,你已经掌握了如何用C语言实现K均值聚类。这种聚类分析C语言的方法不仅高效,而且有助于深入理解算法内部机制。虽然实际项目中可能更多使用Python的scikit-learn库,但自己动手实现能极大提升你的机器学习C语言教程实践能力。

下一步你可以尝试:支持更高维度数据、自动选择最优K值、可视化聚类结果等。祝你在C语言聚类算法的学习道路上越走越远!