返回列表

K-均值聚类算法详解

发布于 ·

K-均值聚类算法详解

一、引言

K-均值(K-means)是机器学习中最经典、最常用的无监督学习算法之一。它通过迭代的方式将数据集中的样本划分为K个簇,使得每个簇内的样本尽可能相似,而不同簇之间的样本尽可能不同。

本文将从K-均值的原理、实现步骤、优缺点以及应用场景等方面进行全面介绍,帮助读者深入理解这一基础但强大的聚类算法。

二、K-均值的原理

2.1 基本思想

K-均值算法的核心思想是通过不断迭代优化来最小化"簇内平方和"(Within-Cluster Sum of Squares, WCSS),即:

WCSS = Σ||x - μ||²

其中x是样本点,μ是对应簇的质心(centroid)。

2.2 算法流程

K-均值的标准流程如下:

  1. 初始化:随机选择K个初始质心
  2. 分配阶段:将每个样本分配到距离最近的质心所在的簇
  3. 更新阶段:重新计算每个簇的质心(所有样本点的均值)
  4. 收敛判断:重复分配和更新步骤,直到质心不再显著变化或达到最大迭代次数

三、算法实现

3.1 Python实现

import numpy as np
import matplotlib.pyplot as plt

class KMeans:
def init(self, k=3, maxiters=100, tol=1e-4):
self.k = k
self.max
iters = maxiters
self.tol = tol

def fit(self, X):
# 初始化质心
n
samples, nfeatures = X.shape
self.centroids = X[np.random.choice(n
samples, self.k, replace=False)]

for _ in range(self.maxiters):
# 分配样本到最近的质心
labels = self.
assignclusters(X)

# 保存旧质心用于收敛判断
old
centroids = self.centroids.copy()

# 更新质心
self.updatecentroids(X, labels)

# 检查是否收敛
if self.isconverged(oldcentroids):
break

return labels

def
assignclusters(self, X):
distances = np.sqrt(((X - self.centroids[:, np.newaxis])**2).sum(axis=2))
return np.argmin(distances, axis=0)

def
updatecentroids(self, X, labels):
for i in range(self.k):
cluster
points = X[labels == i]
if len(clusterpoints) > 0:
self.centroids[i] = cluster
points.mean(axis=0)

def isconverged(self, oldcentroids):
return np.linalg.norm(self.centroids - old
centroids) < self.tol

3.2 使用示例

# 生成测试数据
from sklearn.datasets import makeblobs
X,  = makeblobs(nsamples=300, centers=4, nfeatures=2, 
                  randomstate=42, clusterstd=1.5)

应用K-均值

kmeans = KMeans(k=4) labels = kmeans.fit(X)

可视化结果

plt.figure(figsize=(10, 8)) colors = ['red', 'blue', 'green', 'purple'] for i in range(kmeans.k): cluster
points = X[labels == i] plt.scatter(clusterpoints[:, 0], clusterpoints[:, 1], c=colors[i], alpha=0.6, s=50) plt.scatter(kmeans.centroids[:, 0], kmeans.centroids[:, 1], c='black', marker='x', s=200, linewidths=3) plt.title('K-Means Clustering Results') plt.xlabel('Feature 1') plt.ylabel('Feature 2') plt.show()

四、关键问题与挑战

4.1 K值的选择

选择最优的K值是K-均值面临的主要挑战。常用的方法包括:

  • 肘部法则(Elbow Method):寻找WCSS下降速度明显减缓的点
  • 轮廓系数(Silhouette Score):衡量聚类的紧密性和分离性
  • Gap Statistic:比较实际数据与随机数据的聚类效果

4.2 初始化敏感性问题

K-均值的初始质心选择会影响最终结果。解决方案包括:

  • K-means++:改进的初始化方法,使初始质心分布更合理
  • 多次运行:执行算法多次并选择最佳结果

五、优缺点分析

优点

  • 简单易懂:算法直观,易于理解和实现
  • 高效快速:时间复杂度为O(nkd),适合大规模数据集
  • 可扩展性好:易于并行化和分布式处理

缺点

  • 需要预先指定K值:在实际应用中可能难以确定
  • 对异常值敏感:异常值会影响质心的位置
  • 假设球形簇:不适合发现任意形状的簇
  • 对初始值敏感:不同的初始质心可能导致不同的聚类结果

六、改进版本

6.1 K-means++

K-means++通过改进初始质心的选择来缓解初始化敏感性问题:
def kmeansplusplusinit(X, k):
    nsamples, nfeatures = X.shape
    centroids = np.zeros((k, nfeatures))
    
    # 随机选择第一个质心
    centroids[0] = X[np.random.randint(nsamples)]
    
    for i in range(1, k):
        # 计算每个点到最近质心的距离
        distances = np.array([min([np.sum((x - c)**2) for c in centroids[:i]]) 
                           for x in X])
        probabilities = distances / distances.sum()
        
        # 根据概率选择下一个质心
        cumulativeprobabilities = probabilities.cumsum()
        r = np.random.rand()
        for j, p in enumerate(cumulativeprobabilities):
            if r < p:
                centroids[i] = X[j]
                break
    
    return centroids

6.2 Mini-Batch K-means

适用于超大数据集的改进版本,使用数据子集进行迭代:

from sklearn.cluster import MiniBatchKMeans

minibatchkmeans = MiniBatchKMeans(nclusters=4, batchsize=100)
labels = mini
batchkmeans.fitpredict(X)

七、应用场景

K-均值在实际中有广泛的应用:

  • 客户细分:基于购买行为对客户进行分组

  • 图像压缩:将像素颜色量化为K种主要颜色

  • 文档分类:对文本向量进行聚类

  • 异常检测:识别远离簇中心的异常点

  • 基因表达分析:发现相似的基因表达模式

八、总结

K-均值作为经典的聚类算法,以其简洁性和高效性在数据挖掘和机器学习领域占据重要地位。尽管存在一些局限性,但通过合理的改进和应用场景适配,K-均值仍然是一个非常实用的工具。

掌握K-均值的原理和实现,不仅有助于理解无监督学习的本质,也为深入学习更复杂的聚类算法奠定了坚实基础。