Python实现KMeans算法及Elbow方法确定最佳聚类数

引言

在数据分析和机器学习中,聚类是一种无监督学习方法,用于将数据集分成若干组(簇),使得同一组内的数据点相似度较高,而不同组间的数据点相似度较低。KMeans算法是最常用的聚类算法之一,因其简单高效而广受欢迎。然而,KMeans算法需要预先指定簇的数量(K值),如何选择最佳的K值是一个常见的问题。Elbow方法是一种常用的确定最佳K值的方法。本文将详细介绍如何使用Python实现KMeans算法,并利用Elbow方法确定最佳聚类数。

KMeans算法简介

KMeans算法的基本思想是将数据集分成K个簇,每个簇由一个中心点(质心)代表。算法步骤如下:

  1. 初始化:随机选择K个数据点作为初始质心。
  2. 分配:将每个数据点分配到最近的质心所在的簇。
  3. 更新:计算每个簇内所有点的均值,更新质心。
  4. 迭代:重复步骤2和3,直到质心不再变化或达到最大迭代次数。

Python实现KMeans算法

首先,我们需要导入必要的库:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans

生成一些模拟数据:

# 生成模拟数据
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
plt.scatter(X[:, 0], X[:, 1], s=50)
plt.title("原始数据")
plt.show()

接下来,实现KMeans算法:

def kmeans(X, K, max_iters=100, tol=1e-4):
    # 随机初始化质心
    centroids = X[np.random.choice(range(len(X)), K, replace=False)]
    
    for i in range(max_iters):
        # 计算每个点到质心的距离
        distances = np.linalg.norm(X[:, np.newaxis] - centroids, axis=2)
        # 分配到最近的质心
        labels = np.argmin(distances, axis=1)
        
        # 更新质心
        new_centroids = np.array([X[labels == k].mean(axis=0) for k in range(K)])
        
        # 检查质心是否收敛
        if np.linalg.norm(new_centroids - centroids) < tol:
            break
        
        centroids = new_centroids
    
    return centroids, labels

# 使用自定义的KMeans算法
centroids, labels = kmeans(X, K=4)
plt.scatter(X[:, 0], X[:, 1], c=labels, s=50, cmap='viridis')
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', s=200, marker='X')
plt.title("KMeans聚类结果")
plt.show()

Elbow方法确定最佳聚类数

Elbow方法通过计算不同K值下的簇内平方和(SSE)来确定最佳K值。具体步骤如下:

  1. 对于每个K值,运行KMeans算法。
  2. 计算每个簇的SSE,并求和。
  3. 绘制K值与SSE的关系图,选择“拐点”处的K值。
def calculate_sse(X, centroids, labels):
    sse = 0
    for k in range(len(centroids)):
        sse += np.sum((X[labels == k] - centroids[k]) ** 2)
    return sse

def plot_elbow_method(X, max_k=10):
    sse_list = []
    for k in range(1, max_k + 1):
        centroids, labels = kmeans(X, K=k)
        sse = calculate_sse(X, centroids, labels)
        sse_list.append(sse)
    
    plt.plot(range(1, max_k + 1), sse_list, marker='o')
    plt.xlabel("聚类数K")
    plt.ylabel("簇内平方和SSE")
    plt.title("Elbow方法确定最佳聚类数")
    plt.show()

plot_elbow_method(X)

从图中可以看到,当K值增加到4之后,SSE的下降幅度明显减小,这表明K=4是一个较为合适的聚类数。

结论

本文详细介绍了如何使用Python实现KMeans算法,并通过Elbow方法确定最佳聚类数。KMeans算法简单高效,适用于多种聚类场景,而Elbow方法为选择最佳K值提供了直观的依据。通过本文的示例代码,读者可以更好地理解和应用这些技术,解决实际数据聚类问题。