MNIST 手写数字识别数据集降维与聚类分析
MNIST 手写数字识别数据集降维与聚类分析
本篇文章将介绍 MNIST 数据集、PCA 降维、层次聚类、K-Means 聚类的算法原理及应用,并附上完整的 Python 代码和实验结果。
一、MNIST 数据集
MNIST 是一个经典的手写数字识别数据集,包含 0-9 共 10 个数字的手写图像。每张图像都是 28x28 的灰度图像,被展开成一个 784 (28x28) 维的向量。MNIST 数据集包含 60000 个训练样本和 10000 个测试样本。
二、PCA 降维
PCA (Principal Component Analysis) 是一种常用的数据降维方法,其目的是将高维数据映射到低维空间中,同时尽量保留原有数据的特征信息。PCA 的核心思想是将高维数据映射到一个新的坐标系中,使得数据在新坐标系下的方差最大。具体的降维过程可以通过以下步骤实现:
- 对数据进行中心化处理,使得数据的均值为 0;
- 计算数据的协方差矩阵;
- 对协方差矩阵进行特征值分解,得到特征向量和特征值;
- 按照特征值从大到小的顺序选取前 k 个特征向量,将原始数据映射到这 k 个特征向量构成的新空间中。
在本实验中,我们使用 sklearn 库中的 PCA 函数实现降维,并保留 85% 的能量。
三、层次聚类
层次聚类是一种自下而上的聚类方法,其核心思想是通过不断合并相邻的聚类,形成一个聚类层次结构。在层次聚类中,我们可以选择不同的距离度量方式 (如欧氏距离、曼哈顿距离、余弦距离等) 和聚合方式 (如单链接、完全链接、平均链接等) 来定义相邻聚类之间的距离。具体的聚类过程可以通过以下步骤实现:
- 将每个样本看作一个初始聚类;
- 计算任意两个聚类之间的距离;
- 找到距离最小的两个聚类,将其合并成一个新聚类;
- 重复步骤 2-3,直到所有样本都被合并成一个聚类,形成一个聚类层次结构。
在本实验中,我们使用 sklearn 库中的 AgglomerativeClustering 函数实现层次聚类。
四、K-Means 聚类
K-Means 是一种基于距离的聚类方法,其核心思想是将数据样本分为 k 个簇,使得同一簇内的数据点之间的距离尽可能小,不同簇之间的距离尽可能大。K-Means 聚类的具体步骤如下:
- 随机选择 k 个初始质心;
- 计算每个样本点到各个质心的距离,将其分配到距离最近的簇中;
- 根据当前簇中的样本点重新计算质心;
- 重复步骤 2-3,直到质心不再发生变化或者达到最大迭代次数。
在本实验中,我们使用 sklearn 库中的 KMeans 函数实现 K-Means 聚类。
五、实验过程
下面是实验的完整代码和运行结果。
- 导入必要的库和数据集
from sklearn.datasets import fetch_openml
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans, AgglomerativeClustering
from sklearn.metrics import adjusted_rand_score, silhouette_score
import matplotlib.pyplot as plt
import numpy as np
# 导入 MNIST 数据集
mnist = fetch_openml('mnist_784', version=1)
X = mnist.data
y = mnist.target
- 进行 PCA 降维
# PCA 降维
pca = PCA(n_components=0.85)
X_pca = pca.fit_transform(X)
print('降维后的维度:', X_pca.shape)
- 使用层次聚类进行聚类
# 层次聚类
n_clusters_range = range(2, 11)
best_aris, best_silhouettes = [], []
for n_clusters in n_clusters_range:
model = AgglomerativeClustering(n_clusters=n_clusters)
y_pred = model.fit_predict(X_pca)
# 计算 ARI 和轮廓系数
aris = adjusted_rand_score(y, y_pred)
silhouettes = silhouette_score(X_pca, y_pred)
print('层次聚类:n_clusters=%d, ARI=%.4f, silhouette=%.4f' % (n_clusters, aris, silhouettes))
best_aris.append(aris)
best_silhouettes.append(silhouettes)
# 绘制 ARI 和轮廓系数随簇数变化的曲线
plt.plot(n_clusters_range, best_aris, label='ARI')
plt.plot(n_clusters_range, best_silhouettes, label='Silhouette')
plt.xlabel('Number of Clusters')
plt.legend()
plt.show()
- 使用 K-Means 进行聚类
# K-Means 聚类
n_clusters_range = range(2, 11)
best_aris, best_silhouettes = [], []
for n_clusters in n_clusters_range:
model = KMeans(n_clusters=n_clusters, random_state=42)
y_pred = model.fit_predict(X_pca)
# 计算 ARI 和轮廓系数
aris = adjusted_rand_score(y, y_pred)
silhouettes = silhouette_score(X_pca, y_pred)
print('K-Means:n_clusters=%d, ARI=%.4f, silhouette=%.4f' % (n_clusters, aris, silhouettes))
best_aris.append(aris)
best_silhouettes.append(silhouettes)
# 绘制 ARI 和轮廓系数随簇数变化的曲线
plt.plot(n_clusters_range, best_aris, label='ARI')
plt.plot(n_clusters_range, best_silhouettes, label='Silhouette')
plt.xlabel('Number of Clusters')
plt.legend()
plt.show()
六、实验结果
实验结果如下图所示:

可以看到,在层次聚类中,当簇数为 3 时,ARI 和轮廓系数达到了最优值;在 K-Means 聚类中,当簇数为 4 时,ARI 和轮廓系数达到了最优值。
七、实验结论
本实验使用 PCA 进行降维,并分别应用层次聚类和 K-Means 方法进行聚类。通过实验结果,我们可以得出以下结论:
- 在层次聚类中,当簇数为 3 时,ARI 和轮廓系数达到了最优值;在 K-Means 聚类中,当簇数为 4 时,ARI 和轮廓系数达到了最优值。
- 相比于层次聚类,K-Means 聚类更适合处理大规模数据集,因为其时间复杂度为 O(knd),其中 k 为簇数,n 为数据样本数,d 为数据维度。
- 在实际应用中,我们应该根据具体问题选择不同的聚类方法,并根据聚类效果评价指标来优化超参数,以达到最佳的聚类效果。
原文地址: https://www.cveoy.top/t/topic/op0A 著作权归作者所有。请勿转载和采集!