解密K-means、K-means++ 掌握核心原理

发布于:2025-07-26 ⋅ 阅读:(13) ⋅ 点赞:(0)

K-means算法

K-means算法是一种经典的聚类算法,广泛应用于数据挖掘、图像处理和机器学习等领域。其核心思想是通过迭代的方式将数据划分为K个簇,使得每个簇内的数据点尽可能接近其簇中心,而不同簇之间的数据点尽可能远离。

是一种广泛使用的聚类算法,它的目标是将数据集划分为K个聚类,使得同一聚类内的数据点相似度高,而不同聚类间的数据点相似度低。在Python中,可以通过sklearn库中的KMeans类来实现K-Means算法。

流程图

K-Means算法的基本思想

K-Means算法的基本思想是随机选择K个数据点作为初始质心,然后通过迭代过程不断更新这些质心。在每次迭代中,算法会计算每个数据点到各个质心的距离,并将数据点划分到最近的质心所代表的聚类中。然后,算法会重新计算每个聚类的质心,即聚类中所有点的均值。这个过程会重复进行,直到质心的更新非常小或达到设定的迭代次数为止。

算法步骤

  1. 初始化  随机选择K个数据点作为初始簇中心。

  2. 分配:将每个数据点分配到离其最近的簇中心所在的簇中。

  3. 更新:重新计算每个簇的簇中心,即该簇中所有数据点的均值。

  4. 迭代:重复步骤2和3,直到簇中心不再发生显著变化或达到预设的迭代次数。

示例代码

以下是使用Python中的sklearn库实现K-means聚类的简单示例代码:

import numpy as np

from sklearn.cluster import KMeans

import matplotlib.pyplot as plt
# 假设我们有一些二维数据点
X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]])

# 设定K值为2,即希望将数据划分为2个簇
kmeans = KMeans(n_clusters=2, random_state=0)

# 对数据进行拟合
kmeans.fit(X)

# 获取聚类标签和簇中心
labels = kmeans.labels_
centroids = kmeans.cluster_centers_

# 打印结果
print("Cluster labels:", labels)
print("Cluster centroids:\n", centroids)

# 可视化结果
plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=300, alpha=0.5)
plt.title('K-means Clustering')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.show()

在实际应用中,您可能需要对数据进行预处理(如标准化或归一化),选择适当的K值,并评估聚类结果的质量。

优缺点

优点

  1. 简单易懂:K-means算法的原理相对简单,容易理解。

  2. 收敛速度快:在大多数情况下,K-means算法能够较快速地收敛到局部最优解。

  3. 聚类效果好:对于某些形状和分布的数据集,K-means算法能够产生较好的聚类效果。

缺点

  1. 对初始值敏感:K-means算法的聚类效果受到初始聚类中心选择的影响,不同的初始值可能导致不同的聚类结果。

  2. 局部最优问题:K-means算法采用迭代方法,容易收敛于局部最优解,而非全局最优解。

  3. 对非凸形状聚类效果不佳:对于非凸形状的类簇,K-means算法的识别效果可能较差12

应用场景

K-means算法在各个领域都有着广泛的应用。以下是一些典型的应用场景:

  1. 图像处理:在图像压缩和分割中,K-means算法可以用于将像素点聚类成不同的颜色区域,从而实现图像的颜色量化和区域分割。

  2. 市场分析:在市场营销领域,K-means算法可以根据客户的购买记录、兴趣爱好等信息将客户分群,以便制定更精准的营销策略。

Python代码实现

在Python中,可以使用sklearn库中的KMeans类来实现K-Means算法。以下是一个简单的例子,展示了如何使用KMeans类进行聚类:

from sklearn.cluster import KMeans
import numpy as np

# 创建数据集
X = np.array([[1, 2], [1, 4], [1, 0],[10, 2], [10, 4], [10, 0]])

# 初始化KMeans对象,设置聚类数为2
kmeans = KMeans(n_clusters=2, random_state=0).fit(X)

# 输出聚类标签
print(kmeans.labels_)

# 预测新数据点的聚类
print(kmeans.predict([[0, 0], [12, 3]]))

# 输出聚类中心点
print(kmeans.cluster_centers_)

K-Means算法的评价

K-Means算法的一个挑战是选择合适的K值。一个常用的方法是肘部法则,它通过观察不同K值下聚类的代价函数值来确定最佳的K值。另外,可以使用轮廓系数(Silhouette Coefficient)或Calinski-Harabasz指数来评估聚类的质量。

K-Means算法的优化

K-Means算法对初始质心的选择敏感,可能会陷入局部最小值。为了解决这个问题,可以多次随机初始化质心,并选择代价函数最小的结果作为最终聚类。此外,MiniBatchKMeans是K-Means的一个变种,它使用小批量数据更新质心,适用于大规模数据集。

K-Means的API使用

在sklearn库中,KMeans类提供了丰富的参数来配置聚类过程,如n_clusters用于设置聚类数,max_iter用于设置最大迭代次数,n_init用于设置不同初始化质心运行算法的次数等。通过合理配置这些参数,可以获得更好的聚类效果。

实际应用案例

K-Means算法可以应用于多种场景,如图像分割、文本聚类、市场细分等。例如,可以使用K-Means对图像进行颜色分割,或者对文本文档进行主题聚类。

总结来说,K-Means是一种简单有效的聚类算法,通过sklearn库可以方便地在Python中实现。合理选择K值和参数配置是获得好的聚类效果的关键。

C# K-Means算法

以下不同场景的C# K-Means算法实现示例,涵盖基础实现、图像处理、文本聚类等应用场景。所有代码均基于.NET Core环境,需安装MathNet.Numerics等基础数学库。

基础数值聚类

using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;

public class BasicKMeans
{
    public static List<Vector<double>> Run(List<Vector<double>> data, int k)
    {
        var centroids = InitializeCentroids(data, k);
        var clusters = new int[data.Count];
        
        bool changed;
        do {
            changed = false;
            for (int i = 0; i < data.Count; i++)
            {
                int closest = FindClosestCentroid(data[i], centroids);
                if (clusters[i] != closest) {
                    clusters[i] = closest;
                    changed = true;
                }
            }
            centroids = UpdateCentroids(data, clusters, k);
        } while (changed);
        
        return centroids;
    }
    
    private static List<Vector<double>> InitializeCentroids(List<Vector<double>> data, int k) 
    {
        var random = new Random();
        return data.OrderBy(x => random.Next()).Take(k).ToList();
    }
}

图像颜色量化

使用K-Means压缩图像颜色到16种主色:

using System.Drawing;
using System.Linq;

public class ImageColorQuantizer
{
    public static Color[] Quantize(Bitmap image, int k)
    {
        var pixels = new List<Vector<double>>();
        for (int x = 0; x < ima

网站公告

今日签到

点亮在社区的每一天
去签到