【机器学习】基于t-SNE的MNIST数据集可视化探索
一、前言
在机器学习和数据科学领域,高维数据的可视化是一个极具挑战但又至关重要的问题。高维数据难以直观地理解和分析,而有效的可视化方法能够帮助我们发现数据中的潜在结构、模式和关系。本文以经典的MNIST手写数字数据集为例,探讨如何利用t-分布随机邻域嵌入(t-SNE)这一强大的降维技术,将高维的图像数据降维到二维空间,并进行可视化展示。通过本文,我们将深入了解t-SNE的原理、算法步骤,以及如何在Python中实现并应用它,从而更好地理解和探索高维数据的内在特性。
二、技术与原理简介
在深入探讨t-SNE之前,我们首先需要区分机器学习中的两大主要范畴:监督学习和无监督学习。
1. 监督学习
监督学习是指在已知输入数据和对应标签的情况下,训练模型学习输入与输出之间的映射关系。模型通过学习大量的带标签数据,能够对新的、未见过的数据进行预测或分类。常见的监督学习算法包括:
- 线性回归: 用于预测连续型变量。
- 逻辑回归: 用于分类问题。
- 支持向量机 (SVM): 用于分类和回归问题,尤其擅长处理高维数据。
- 决策树: 基于树状结构进行决策,易于理解和解释。
- 随机森林: 集成多个决策树,提高预测的准确性和鲁棒性。
- 神经网络: 模拟人脑神经元结构,能够学习复杂的非线性关系。
2. 无监督学习
无监督学习是指在没有标签的情况下,训练模型发现数据中的潜在结构和模式。模型通过分析数据的内在特征,能够进行聚类、降维、关联规则挖掘等任务。常见的无监督学习算法包括:
- 聚类: 将数据划分为不同的簇,使得同一簇内的数据相似度较高,不同簇之间的数据相似度较低。常见的聚类算法包括K-means、层次聚类、DBSCAN等。
- 降维: 将高维数据降维到低维空间,同时尽可能保留数据的关键信息。常见的降维算法包括主成分分析 (PCA)、t-SNE、UMAP等。
- 关联规则挖掘: 发现数据中不同项之间的关联关系,例如购物篮分析。
3. 监督学习与无监督学习的区别
4. MNIST数据集简介
MNIST (Modified National Institute of Standards and Technology database) 是一个经典的手写数字数据集,广泛应用于机器学习和深度学习领域。它包含60,000个训练样本和10,000个测试样本,每个样本都是一个28x28像素的灰度图像,代表0到9之间的手写数字。
4.1 数据格式
MNIST数据集通常以两种格式提供:
- 图像格式: 每个样本都是一个图像文件,例如PNG或JPEG格式。
- 数值格式: 每个样本都被转换为一个784维的向量,其中每个元素代表一个像素的灰度值 (0到255)。
4.2 数据集特点
- 规模适中: MNIST数据集的规模适中,既可以用于快速原型验证,又可以用于训练复杂的模型。
- 易于获取: MNIST数据集可以从多个来源免费获取,例如Scikit-learn、TensorFlow等。
- 广泛应用: MNIST数据集被广泛应用于各种机器学习和深度学习算法的评估和比较。
5. t-SNE算法原理与数学推导
5.1 算法核心思想
t-SNE(t-Distributed Stochastic Neighbor Embedding)是一种非线性降维技术,通过以下步骤实现高维数据到低维空间的映射:
- 计算高维相似度:在原始空间中,计算每对样本间的相似度
- 构建低维嵌入空间:在目标空间(如2D)中,通过优化使相似度分布匹配
- 梯度下降优化:最小化两空间分布的KL散度
5.2 数学公式详解
5.2.1 高维相似度计算
对原始空间中的样本对(𝑥𝑖,𝑥𝑗) ,定义条件概率:
其中𝜎𝑖 为高斯核带宽,通过二分查找确定以满足** perplexity **参数(控制邻域大小)。
5.2.2 低维相似度建模
在目标空间中,定义联合概率:
采用t-分布(自由度为1的Student分布)以增强对异常值的鲁棒性。
5.2.3 目标函数优化
通过最小化KL散度实现分布匹配:
其中
优化过程使用梯度下降:
5.3 算法步骤流程
- 参数初始化:设置降维维度(如2D)、perplexity(通常5-50)、学习率等
- 高维相似度计算:为每个样本计算条件概率矩阵𝑃P
- 低维初始化:随机生成初始嵌入坐标𝑌Y
- 梯度下降优化:迭代更新𝑌Y以最小化KL散度
- 结果输出:返回低维坐标矩阵
三、代码详解
本文的代码主要分为以下几个部分:
1. 导入库
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn import datasets
from sklearn import manifold
%matplotlib inline
说明:
import matplotlib.pyplot as plt
: 导入matplotlib库,用于绘制图像。import numpy as np
: 导入numpy库,用于进行数值计算。import pandas as pd
: 导入pandas库,用于数据处理。import seaborn as sns
: 导入seaborn库,用于数据可视化。from sklearn import datasets
: 导入sklearn库中的datasets模块,用于加载数据集。from sklearn import manifold
: 导入sklearn库中的manifold模块,用于降维。%matplotlib inline
: 在Jupyter Notebook中显示图像。
2. 加载数据
# 加载数据
data = datasets.fetch_openml('mnist_784', version=1, return_X_y=True)
pixel_values, targets = data
targets = targets.astype(int)
# 将DataFrame转换为numpy数组以便更容易操作
# 如果pixel_values已经是numpy数组,这一步可以跳过
if isinstance(pixel_values, pd.DataFrame):
pixel_values_array = pixel_values.values
else:
pixel_values_array = pixel_values
说明:
data = datasets.fetch_openml('mnist_784', version=1, return_X_y=True)
: 使用datasets.fetch_openml
函数加载MNIST数据集。'mnist_784'
表示数据集的名称,version=1
表示数据集的版本,return_X_y=True
表示返回输入数据和标签。pixel_values, targets = data
: 将返回的数据解包为pixel_values
和targets
。pixel_values
包含图像的像素值,targets
包含图像的标签。targets = targets.astype(int)
: 将标签转换为整数类型。if isinstance(pixel_values, pd.DataFrame):
: 检查pixel_values
是否为pandas DataFrame类型。pixel_values_array = pixel_values.values
: 如果pixel_values
为pandas DataFrame类型,则将其转换为numpy数组。else: pixel_values_array = pixel_values
: 否则,直接使用pixel_values
。
3. 显示单个图像
# 显示单个图像
single_image = pixel_values_array[1].reshape(28, 28)
plt.imshow(single_image, cmap='gray')
说明:
single_image = pixel_values_array[1].reshape(28, 28)
: 选择第一个图像,并将其reshape为28x28的矩阵。plt.imshow(single_image, cmap='gray')
: 使用plt.imshow
函数显示图像,cmap='gray'
表示使用灰度颜色映射。
4. t-SNE降维
# t-SNE降维
tsne = manifold.TSNE(n_components=2, random_state=42)
transformed_data = tsne.fit_transform(pixel_values_array[:3000])
说明:
tsne = manifold.TSNE(n_components=2, random_state=42)
: 创建一个t-SNE对象。n_components=2
表示将数据降维到二维空间,random_state=42
表示设置随机种子,保证结果的可重复性。transformed_data = tsne.fit_transform(pixel_values_array[:3000])
: 使用fit_transform
函数对数据进行降维。这里只使用了前3000个样本,因为t-SNE的计算复杂度较高。
5. 创建DataFrame用于可视化
# 创建DataFrame用于可视化
tsne_df = pd.DataFrame(
np.column_stack((transformed_data, targets[:3000])),
columns=["x", "y", "targets"]
)
tsne_df.loc[:, "targets"] = tsne_df.targets.astype(int)
说明:
tsne_df = pd.DataFrame(...)
: 创建一个pandas DataFrame对象,用于存储降维后的数据和标签。np.column_stack((transformed_data, targets[:3000]))
: 将降维后的数据和标签按列拼接在一起。columns=["x", "y", "targets"]
: 设置DataFrame的列名。tsne_df.loc[:, "targets"] = tsne_df.targets.astype(int)
: 将DataFrame中的标签转换为整数类型。
6. 可视化
# 可视化
# 注意:在新版本的seaborn中,size参数已更改为height
try:
grid = sns.FacetGrid(tsne_df, hue="targets", size=8)
except TypeError:
grid = sns.FacetGrid(tsne_df, hue="targets", height=8)
grid.map(plt.scatter, "x", "y").add_legend()
说明:
grid = sns.FacetGrid(tsne_df, hue="targets", size=8)
: 创建一个seaborn FacetGrid对象,用于可视化降维后的数据。hue="targets"
表示使用标签作为颜色编码,size=8
表示设置图像的大小。grid.map(plt.scatter, "x", "y").add_legend()
: 使用plt.scatter
函数绘制散点图,"x"
和"y"
表示散点图的横坐标和纵坐标,add_legend()
表示添加图例。
7. 完整代码
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from sklearn import datasets
from sklearn import manifold
%matplotlib inline
# 加载数据
data = datasets.fetch_openml('mnist_784', version=1, return_X_y=True)
pixel_values, targets = data
targets = targets.astype(int)
# 将DataFrame转换为numpy数组以便更容易操作
# 如果pixel_values已经是numpy数组,这一步可以跳过
if isinstance(pixel_values, pd.DataFrame):
pixel_values_array = pixel_values.values
else:
pixel_values_array = pixel_values
# 显示单个图像
single_image = pixel_values_array[1].reshape(28, 28)
plt.imshow(single_image, cmap='gray')
# t-SNE降维
tsne = manifold.TSNE(n_components=2, random_state=42)
transformed_data = tsne.fit_transform(pixel_values_array[:3000])
# 创建DataFrame用于可视化
tsne_df = pd.DataFrame(
np.column_stack((transformed_data, targets[:3000])),
columns=["x", "y", "targets"]
)
tsne_df.loc[:, "targets"] = tsne_df.targets.astype(int)
# 可视化
# 注意:在新版本的seaborn中,size参数已更改为height
try:
grid = sns.FacetGrid(tsne_df, hue="targets", size=8)
except TypeError:
grid = sns.FacetGrid(tsne_df, hue="targets", height=8)
grid.map(plt.scatter, "x", "y").add_legend()
四、总结与思考
本文以MNIST数据集为例,详细介绍了如何使用t-SNE进行高维数据可视化。通过t-SNE降维,我们可以将784维的图像数据降维到二维空间,并在散点图上清晰地看到不同数字之间的分布情况。
t-SNE是一种强大的降维技术,但也有一些局限性:
- 计算复杂度高: t-SNE的计算复杂度为O(n^2),对于大规模数据集,计算时间会非常长。
- 参数敏感: t-SNE的性能受到参数的影响,例如困惑度 (perplexity) 和学习率 (learning_rate)。
- 全局结构失真: t-SNE主要关注局部结构,可能会导致全局结构失真。
在实际应用中,我们需要根据具体情况选择合适的降维技术。对于大规模数据集,可以考虑使用PCA或UMAP等更高效的算法。对于需要保留全局结构的场景,可以考虑使用Isomap或LLE等算法。
【作者声明】
本文内容基于作者对基于t-SNE的MNIST数据集可视化探索实现过程的实验与总结,所有数据和代码均为原创。文章中的观点仅代表个人见解,供读者参考交流。若有任何问题或建议,欢迎在评论区留言讨论,共同促进技术进步。
【关注我们】
如果您对神经网络、群智能算法及人工智能技术感兴趣,欢迎点赞、收藏并转发,与更多朋友一起探讨与交流!