简介
在本实验中,我们将探索 k 均值聚类算法及其假设。我们将生成具有不同分布的数据,并可视化 k 均值如何将这些数据划分为簇。我们还将讨论该算法的一些局限性以及克服这些局限性的可能解决方案。
虚拟机使用提示
虚拟机启动完成后,点击左上角切换到“笔记本”标签,以访问 Jupyter Notebook 进行练习。
有时,你可能需要等待几秒钟让 Jupyter Notebook 完成加载。由于 Jupyter Notebook 的限制,操作验证无法自动化。
如果你在学习过程中遇到问题,请随时向 Labby 提问。课程结束后提供反馈,我们将立即为你解决问题。
数据生成
我们将使用 scikit-learn 中的 make_blobs 函数来生成具有不同分布的不同数据集。在以下代码块中,我们生成四个数据集:
- 高斯混合聚类
- 各向异性分布的聚类
- 方差不等的聚类
- 大小不均的聚类
import numpy as np
from sklearn.datasets import make_blobs
n_samples = 1500
random_state = 170
transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]
X, y = make_blobs(n_samples=n_samples, random_state=random_state)
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
数据可视化
我们将使用 Matplotlib 来可视化生成的数据集。在以下代码块中,我们创建了一个 2x2 的图表,展示了每个数据集的真实聚类情况。
import matplotlib.pyplot as plt
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("真实聚类情况").set_y(0.95)
plt.show()
K 均值聚类
我们将使用 scikit-learn 中的 KMeans 类对数据进行聚类。在以下代码块中,我们创建了一个 2x2 的图表,展示了 k 均值算法对每个数据集所得到的聚类结果。
from sklearn.cluster import KMeans
common_params = {
"n_init": "auto",
"random_state": random_state,
}
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(12, 12))
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("非最优聚类数")
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("各向异性分布的聚类")
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("方差不等")
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 聚类结果").set_y(0.95)
plt.show()
可能的解决方案
我们将讨论一些针对 k 均值聚类局限性的可能解决方案。在以下代码块中,我们展示了如何为第一个数据集找到正确的聚类数,以及如何通过增加随机初始化的次数来处理大小不均的聚类。
y_pred = KMeans(n_clusters=3, **common_params).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.title("最优聚类数")
plt.show()
y_pred = KMeans(n_clusters=3, n_init=10, random_state=random_state).fit_predict(
X_filtered
)
plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred)
plt.title("大小不均的聚类 \n多次初始化")
plt.show()
高斯混合模型
我们将探讨高斯混合模型的使用,它能够处理各向异性和方差不等的分布。在以下代码块中,我们使用 GaussianMixture 对第二个和第三个数据集进行聚类。
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("高斯混合聚类").set_y(0.95)
plt.show()
总结
在本实验中,我们探讨了 k 均值聚类算法及其假设。我们生成了具有不同分布的各种数据集,并可视化了 k 均值如何将这些数据划分为聚类。我们还讨论了该算法的一些局限性以及克服这些局限性的可能解决方案,包括找到正确的聚类数、增加随机初始化的次数以及使用高斯混合模型。