本教程介绍如何结合 KMeans 聚类 和 主成分分析 (PCA),对手写数字数据集 (digits) 进行聚类分析。通过聚类方法,我们尝试将手写数字图片的高维特征压缩到低维空间,评估聚类性能,并使用可视化工具展示聚类结果。
加载 sklearn 中的手写数字数据集,并获取其数据特征和目标类别信息:
from sklearn import datasets
# 加载数据集
digits = datasets.load_digits()
X, y = digits.data, digits.target
n_samples, n_features = X.shape
n_classes = len(np.unique(y))
print(f"数据集详情: {n_classes} 类别; {n_samples} 样本; {n_features} 特征")
聚类结果评价使用以下指标:
同质性(Homogeneity): 每个群集中只包含一个真实类别。
完整性(Completeness): 一个真实类别的样本尽可能分配到同一群集中。
V 测度(V-Measure): 同质性和完整性的加权平均。
调整后的兰德指数(ARI): 衡量真实标签与聚类标签的一致性。
调整后的互信息(AMI): 衡量信息论意义上的相似性。
轮廓系数(Silhouette): 衡量样本在聚类中的紧密性和分离性。
from sklearn import metrics
from time import time
def evaluate_clustering(model, data, labels, name):
start_time = time()
model.fit(data)
elapsed_time = time() - start_time
inertia = model.inertia_
# 聚类评价指标
clustering_metrics = [
metrics.homogeneity_score(labels, model.labels_),
metrics.completeness_score(labels, model.labels_),
metrics.v_measure_score(labels, model.labels_),
metrics.adjusted_rand_score(labels, model.labels_),
metrics.adjusted_mutual_info_score(labels, model.labels_),
]
# 轮廓系数
silhouette = metrics.silhouette_score(data, model.labels_, metric="euclidean", sample_size=300)
# 打印结果
results = [name, elapsed_time, inertia] + clustering_metrics + [silhouette]
result_format = "{:<15} {:>8.3f}s {:>7} {:>6.3f} {:>6.3f} {:>6.3f} {:>6.3f} {:>6.3f} {:>6.3f}"
print(result_format.format(*results))
尝试以下 KMeans 初始化方法:
k-means++: 更高效的初始簇分配策略。
随机初始化: 通过随机选点初始化。
PCA 初始化: 利用 PCA 降维的主成分初始化。
from sklearn.cluster import KMeans
models = [
("K-means++ init", KMeans(n_clusters=n_classes, init="k-means++", n_init=4, random_state=0)),
("Random init", KMeans(n_clusters=n_classes, init="random", n_init=4, random_state=0)),
]
for name, model in models:
evaluate_clustering(model, X, y, name)
# PCA-based initialization
from sklearn.decomposition import PCA
pca_model = PCA(n_components=n_classes).fit(X)
kmeans_pca = KMeans(init=pca_model.components_, n_clusters=n_classes, n_init=1, random_state=0)
evaluate_clustering(kmeans_pca, X, y, "PCA-based init")
将高维数据降维到 2 维,用 PCA 提取最主要的两个成分。对降维后的数据重新聚类并可视化。
# PCA reduction to 2D
reduced_X = PCA(n_components=2).fit_transform(X)
reduced_kmeans = KMeans(init="k-means++", n_clusters=n_classes, n_init=4)
reduced_kmeans.fit(reduced_X)
# Visualization setup
x_min, x_max = reduced_X[:, 0].min() - 1, reduced_X[:, 0].max() + 1
y_min, y_max = reduced_X[:, 1].min() - 1, reduced_X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02))
Z = reduced_kmeans.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.figure(figsize=(8, 6))
plt.imshow(Z, interpolation="nearest", extent=(xx.min(), xx.max(), yy.min(), yy.max()),
cmap=plt.cm.Paired, aspect="auto", origin="lower")
plt.scatter(reduced_X[:, 0], reduced_X[:, 1], c=reduced_kmeans.labels_, edgecolors="k", s=30)
centroids = reduced_kmeans.cluster_centers_
plt.scatter(centroids[:, 0], centroids[:, 1], marker="x", s=200, c="white", zorder=10)
plt.title("KMeans on PCA-reduced Digits Dataset\nCentroids marked with white cross")
plt.xlabel("PCA Component 1")
plt.ylabel("PCA Component 2")
plt.xticks(())
plt.yticks(())
plt.show()
Initialization Time Inertia Homogeneity Completeness V-Measure ARI AMI Silhouette
K-means++ init 0.053s 1165177.7137062165 0.742 0.751 0.747 0.669 0.744 0.176
Random init 0.024s 1165142.0046186217 0.739 0.748 0.744 0.666 0.741 0.168
PCA-based init 0.020s 1188310.429252924 0.784 0.787 0.785 0.741 0.783 0.168
因篇幅问题不能全部显示,请点此查看更多更全内容