如何实现C#中的K均值聚类算法

来源:开发教程作者:不吃香菜头衔:草根站长
导读:本期聚焦于小伙伴创作的《如何实现C#中的K均值聚类算法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何实现C#中的K均值聚类算法》有用,将其分享出去将是对创作者最好的鼓励。

K均值聚类是一种经典的无监督学习算法,核心目标是将无标签的样本数据划分成K个簇,让同一个簇内的样本相似度尽可能高,不同簇之间的样本相似度尽可能低。在C#中实现该算法,需要先理解算法的核心流程,再逐步编写对应的代码逻辑。

如何实现C#中的K均值聚类算法

K均值聚类核心原理

K均值聚类的执行流程可以分为几个固定步骤,首先需要从所有样本中随机选择K个样本作为初始聚类中心,然后遍历所有样本,计算每个样本到各个聚类中心的距离,将样本划分到距离最近的聚类中心所在的簇中。完成所有样本的分类后,重新计算每个簇的均值,将这个均值作为新的聚类中心,重复上述分类和更新中心的步骤,直到聚类中心不再发生变化或者达到预设的迭代次数。

C#实现步骤拆解

1. 定义样本和聚类中心结构

首先需要定义存储样本数据和聚类中心的数据结构,这里以二维样本为例,每个样本包含两个特征维度,聚类中心的结构和样本结构一致。

// 定义样本结构,包含x和y两个特征维度
public class DataPoint
{
    public double X { get; set; }
    public double Y { get; set; }
}

// 定义聚类中心结构,和样本结构一致,额外存储所属簇的样本列表
public class ClusterCenter
{
    public double X { get; set; }
    public double Y { get; set; }
    // 存储该簇包含的所有样本
    public List<DataPoint> Points { get; set; } = new List<DataPoint>();
}

2. 计算两个样本之间的欧氏距离

K均值聚类通常使用欧氏距离衡量样本之间的相似度,距离越小说明两个样本越相似。下面实现欧氏距离的计算逻辑。

// 计算两个数据点的欧氏距离
public static double CalculateDistance(DataPoint p1, DataPoint p2)
{
    double dx = p1.X - p2.X;
    double dy = p1.Y - p2.Y;
    return Math.Sqrt(dx * dx + dy * dy);
}

3. 初始化聚类中心

初始化聚类中心时,从所有样本中随机选择K个不重复的样本作为初始中心,避免初始中心选择不当导致算法收敛到局部最优。

// 随机初始化K个聚类中心
public static List<ClusterCenter> InitializeCenters(List<DataPoint> dataPoints, int k)
{
    List<ClusterCenter> centers = new List<ClusterCenter>();
    Random random = new Random();
    // 用来记录已经选中的样本索引,避免重复选择
    HashSet<int> selectedIndexes = new HashSet<int>();
    while (centers.Count < k)
    {
        int index = random.Next(dataPoints.Count);
        if (!selectedIndexes.Contains(index))
        {
            selectedIndexes.Add(index);
            DataPoint point = dataPoints[index];
            centers.Add(new ClusterCenter { X = point.X, Y = point.Y });
        }
    }
    return centers;
}

4. 样本分类与中心更新

遍历所有样本,将每个样本分配到距离最近的聚类中心所在的簇,然后重新计算每个簇的均值作为新的聚类中心。

// 执行一次样本分类和中心更新,返回是否发生中心变化
public static bool UpdateClusters(List<DataPoint> dataPoints, List<ClusterCenter> centers)
{
    // 先清空每个簇的样本列表
    foreach (var center in centers)
    {
        center.Points.Clear();
    }
    // 遍历所有样本,分配到最近的簇
    foreach (var point in dataPoints)
    {
        double minDistance = double.MaxValue;
        ClusterCenter closestCenter = null;
        foreach (var center in centers)
        {
            double distance = CalculateDistance(point, new DataPoint { X = center.X, Y = center.Y });
            if (distance < minDistance)
            {
                minDistance = distance;
                closestCenter = center;
            }
        }
        closestCenter.Points.Add(point);
    }
    // 更新每个簇的中心,计算所有样本的均值
    bool centerChanged = false;
    foreach (var center in centers)
    {
        if (center.Points.Count == 0) continue;
        double newX = center.Points.Average(p => p.X);
        double newY = center.Points.Average(p => p.Y);
        if (Math.Abs(newX - center.X) > 0.0001 || Math.Abs(newY - center.Y) > 0.0001)
        {
            center.X = newX;
            center.Y = newY;
            centerChanged = true;
        }
    }
    return centerChanged;
}

5. 完整算法整合

将上述步骤整合起来,实现完整的K均值聚类算法,支持设置最大迭代次数避免无限循环。

// 完整的K均值聚类算法实现
public static List<ClusterCenter> KMeansClustering(List<DataPoint> dataPoints, int k, int maxIterations = 100)
{
    // 初始化聚类中心
    List<ClusterCenter> centers = InitializeCenters(dataPoints, k);
    int iteration = 0;
    bool centerChanged = true;
    // 循环迭代直到中心不再变化或者达到最大迭代次数
    while (centerChanged && iteration < maxIterations)
    {
        centerChanged = UpdateClusters(dataPoints, centers);
        iteration++;
    }
    return centers;
}

使用示例

下面是一段调用上述K均值聚类算法的示例代码,使用一组随机生成的二维样本进行测试。

class Program
{
    static void Main(string[] args)
    {
        // 生成测试样本数据
        List<DataPoint> testData = new List<DataPoint>
        {
            new DataPoint { X = 1.0, Y = 1.0 },
            new DataPoint { X = 1.5, Y = 2.0 },
            new DataPoint { X = 3.0, Y = 4.0 },
            new DataPoint { X = 5.0, Y = 7.0 },
            new DataPoint { X = 3.5, Y = 5.0 },
            new DataPoint { X = 4.5, Y = 5.0 },
            new DataPoint { X = 3.5, Y = 4.5 }
        };
        // 调用K均值聚类,分成2个簇
        List<ClusterCenter> result = KMeansClustering(testData, 2);
        // 输出聚类结果
        for (int i = 0; i < result.Count; i++)
        {
            Console.WriteLine($"簇{i + 1}的中心坐标:({result[i].X:F2}, {result[i].Y:F2})");
            Console.WriteLine($"簇{i + 1}包含的样本数量:{result[i].Points.Count}");
            foreach (var point in result[i].Points)
            {
                Console.WriteLine($"  样本坐标:({point.X:F2}, {point.Y:F2})");
            }
        }
    }
}

注意事项

  • K值的选择对聚类结果影响很大,实际使用时可以通过肘部法则等方法选择合适的K值。
  • 初始聚类中心的选择可能导致算法收敛到局部最优,可以多次运行算法选择效果最好的一次结果。
  • 如果样本的特征维度超过2维,只需要扩展DataPointClusterCenter的属性,同时调整距离计算的逻辑即可适配更高维度的数据。
  • 当某个簇中没有样本时,可以重新随机选择一个样本作为该簇的新中心,避免空簇影响聚类结果。

K_means聚类算法C#修改时间:2026-06-11 06:12:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。