数据聚类分析与KMeans算法

在数据分析中,聚类是一种常用的无监督学习方法,用于将数据点分组,使得同一组内的数据点相似度高,不同组之间的相似度低。KMeans算法是聚类分析中一个非常流行的算法,它通过迭代优化的方式将数据点分配到不同的簇中。然而,KMeans算法在处理某些特定类型的数据分布时可能会遇到挑战,例如非等方差或非等大小的聚类。本文将探讨这些问题,并提供可能的解决方案。

数据生成

为了模拟不同的数据分布,可以使用Python中的make_blobs函数生成高斯分布的数据点。通过定义线性变换,可以生成非等轴(椭圆形)的高斯分布。此外,还可以生成具有不同方差和不同大小的聚类。

from sklearn.datasets import make_blobs import numpy as np import matplotlib.pyplot as plt # 设置随机种子和样本数量 random_state = 170 n_samples = 1500 # 生成等轴高斯分布 X, y = make_blobs(n_samples=n_samples, random_state=random_state) # 定义线性变换生成非等轴高斯分布 transformation = np.array([[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]) X_aniso = np.dot(X, transformation) # 生成具有不同方差的高斯分布 X_varied, y_varied = make_blobs(n_samples=n_samples, cluster_std=[1.0, 2.5, 0.5], random_state=random_state) # 生成不同大小的聚类 X_filtered = np.vstack((X[y == 0][:500], X[y == 1][:100], X[y == 2][:10])) y_filtered = [0]*500 + [1]*100 + [2]*10

数据可视化

为了更好地理解数据的分布,可以使用散点图来可视化这些数据点。通过不同的颜色来区分不同的聚类,可以直观地看到数据点是如何被分组的。

fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12)) # 绘制等轴高斯分布 axs[0, 0].scatter(X[:, 0], X[:, 1], c=y) axs[0, 0].set_title("等轴高斯聚类") # 绘制非等轴高斯分布 axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y) axs[0, 1].set_title("非等轴高斯聚类") # 绘制具有不同方差的高斯分布 axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_varied) axs[1, 0].set_title("不同方差聚类") # 绘制不同大小的聚类 axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_filtered) axs[1, 1].set_title("不同大小聚类") plt.suptitle("数据聚类可视化") plt.show()

KMeans算法的应用

KMeans算法通过最小化样本到其分配簇的质心的欧几里得距离来进行聚类。然而,当数据分布是非等轴或具有不同方差时,KMeans算法可能无法得到理想的聚类结果。此外,如果聚类的大小不均匀,KMeans算法可能需要多次运行以避免陷入局部最小值。

from sklearn.cluster import KMeans # 设置KMeans算法的参数 common_params = {"n_init": "auto", "random_state": random_state} fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12)) # 应用KMeans算法到等轴高斯分布 y_pred = KMeans(n_clusters=2, **common_params).fit_predict(X) axs[0, 0].scatter(X[:, 0], X[:, 1], c=y_pred) axs[0, 0].set_title("非理想聚类数量") # 应用KMeans算法到非等轴高斯分布 y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_aniso) axs[0, 1].scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred) axs[0, 1].set_title("非等轴分布聚类") # 应用KMeans算法到具有不同方差的高斯分布 y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_varied) axs[1, 0].scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred) axs[1, 0].set_title("不同方差聚类") # 应用KMeans算法到不同大小的聚类 y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X_filtered) axs[1, 1].scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred) axs[1, 1].set_title("不同大小聚类") plt.suptitle("KMeans聚类结果") plt.show()

可能的解决方案

为了解决KMeans算法在处理非等轴或具有不同方差数据分布时的局限性,可以考虑使用高斯混合模型(GaussianMixture)。与KMeans算法不同,高斯混合模型不要求簇具有相同的方差,因此更适合处理这类数据分布。此外,还可以通过增加随机初始化的次数来避免KMeans算法陷入局部最小值。

from sklearn.mixture import GaussianMixture # 设置高斯混合模型的参数 fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(12, 6)) # 应用高斯混合模型到非等轴高斯分布 y_pred = GaussianMixture(n_components=3).fit_predict(X_aniso) ax1.scatter(X_aniso[:, 0], X_aniso[:, 1], c=y_pred) ax1.set_title("非等轴分布聚类") # 应用高斯混合模型到具有不同方差的高斯分布 y_pred = GaussianMixture(n_components=3).fit_predict(X_varied) ax2.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred) ax2.set_title("不同方差聚类") plt.suptitle("高斯混合模型聚类结果") plt.show()

在高维空间中,欧几里得距离往往会膨胀,导致KMeans算法的性能下降。在这种情况下,可以通过降维算法来缓解这个问题,并加速计算过程。如果已知聚类是等轴的、具有相似的方差且不太稀疏,KMeans算法是非常有效且快速的聚类算法之一。然而,如果需要多次运行算法以避免收敛到局部最小值,这种优势就会丧失。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485