主成分分析(PCA)及其在MNIST数据集上的应用

在本文中,将探讨主成分分析(PCA)这一技术,并将其应用于MNIST数据集。在深入PCA技术之前,首先需要了解PCA是什么,它的几何解释,数学公式,以及如何在MNIST数据集上实现PCA。PCA是一种维度降低技术,它将n维数据减少到n'维,其中n大于n'。许多数据集拥有大量特征,这些特征即数据点的广度。在这些数据集中,有些特征对最终结果的影响较小,并且增加了机器学习模型的处理时间。人类只能在2D和3D中可视化数据,而无法想象更高维度的数据。为了解决可视化和优化问题,机器学习中有许多技术,如PCA、t-SNE、随机森林、核PCA、截断SVD等。

本文将使用的数据集是MNIST数据集,它包含了0到9的手写数字信息。在这个数据集中,单个数字的信息以784*1数组的形式存储,其中784*1数组的单个元素代表28*28图像的单个像素。这里单个像素的值从0到1不等,其中黑色由1表示,白色由0表示,中间值代表灰色阴影。

PCA的几何解释:PCA的工作是降低给定数据集的维度。也就是说,如果有一个d维数据集,那么任务是将数据转换为d'维数据,其中d大于d'。为了理解PCA的几何解释,将以一个2D数据集为例,并将其转换为1D数据集,因为无法想象超过3D的数据。但从2D解释中学到的任何东西,也可以做在更高维度上。

现在让来看一个例子,假设有一个DxN维数据集X,其中d=2,n=20,数据集的两个特征是f1和f2。现在让看看用这些数据制作的散点图,其数据分布如下所示。看了散点图后,很容易就能说出f1的特征方差远大于f2的特征方差。与f1的变异性相比,f2的变异性不重要。如果要在f1和f1之间选择一个特征,可以很容易地选择f1特征。现在假设无法可视化2D数据,为了可视化数据,必须将2D数据转换为1D数据,会怎么做?所以简单的答案是直接保留那些方差最高的特性,并移除那些对整体结果影响较小的特性。这就是PCA内部所做的。

首先,确保数据是标准化的,因为在标准化数据上执行PCA比原始数据要容易得多。所以现在再次让看看有一个d*n维数据集X,其中d=2,n=20,数据集的两个特征是f1和f2。并且记住已经标准化了数据。但在这种情况下,散点图看起来像这样。在这种情况下,如果要从2D降低到1D,就不能清楚地选择f1或f2,因为这次两个特征的方差几乎相同,两个特征似乎都很重要。那么PCA是怎么做的呢?

在这种情况下,PCA试图在数据方差很高的方向上画一条线。也就是说,不是在f1或f1轴上投影数据或测量方差,而是在f1'或f2'方向上量化方差,因为在f1'或f2'方向上测量方差更有意义。所以PCA试图找到数据方差很高的向量或线的方向。数据方差最高的向量方向称为PC1(第一主成分),第二高的是PC2,第三是PC3,以此类推。

PCA的数学公式:已经展示了PCA的几何直觉,展示了PCA如何降低数据的维度。所以PCA简单地找到方向并画出方差很高的向量,但可能想知道PCA是如何做到的,以及它如何找到方差很高的向量的正确方向。PCA如何计算角度并给准确的斜率。所以PCA使用两种技术来找到向量的角度。这两种方法是方差最大化和距离最小化。让简要了解一下它们。

1. 方差最大化:在这种方法中,简单地将所有数据点投影到单位向量u1上,并找到所有投影数据点的方差。选择方差最大的方向。所以让假设有一个二维数据集,数据集的特征是f1和f2,xi是数据点,u1是单位向量。如果将数据点xi投影到u1上,投影点是xi',u1=单位向量||u1||=1(单位向量的长度)f1和f2=数据集的特征xi=数据点xi'=u1*xi/||u1||假设u1是单位向量,所以单位向量的长度||u1||=1=>xi'=u1*xi=>xi'=u1T*xi……(1)现在x^'=u1T*x^………..(2)[x^=x的平均值]所以找到u1,使得投影xi到u1的方差最大化var{u1T*xi}(i是1到n)如果数据是列标准化的,那么平均值=0,方差=1所以x^=[0, 0, 0… .. . . .0]=>u1T*x^=0想要最大化方差。

2. 距离最小化:在PCA的这种技术中,试图最小化数据点到u1(长度为1的单位向量)的距离||xi||2=di2+(u1T*xi)2[勾股定理]di2=||xi||2–(u1T*xi)2=>di2=xiT*xi–(u1T*xi)2想要最小化所有距离平方的和。

MNIST数据集上实现PCA:正如之前讨论的MNIST数据集,刚刚完成了对PCA的理解,所以现在是在MNIST数据集上执行PCA这个降维技术的最好时机,实现将从零开始,所以不要再浪费时间了,让开始吧。

首先,导入实现PCA所需的Python库。

import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns

现在让从计算机上加载MNIST数据集,该数据集以.csv格式存储。为了简单起见,只导入了20000行,可以从以下链接下载MNIST数据集:

df = pd.read_csv('mnist_train.csv', nrows = 20000) print("the shape of data is :", df.shape) df.head()

运行上述代码以查看输出。

从数据集中提取标签列。

label = df['label'] df.drop('label', axis = 1, inplace = True)

使用matplotlib的imshow()方法绘制数据集中的随机样本点。

ind = np.random.randint(0, 20000) plt.figure(figsize = (20, 5)) grid_data = np.array(df.iloc[ind]).reshape(28,28) plt.imshow(grid_data, interpolation = None, cmap = 'gray') plt.show() print(label[ind])

使用sklearn.preprocessing模块的StandardScalar类对数据集进行列标准化,因为在对数据进行列标准化之后,每个特征的平均值变为0(零),方差为1。所以从原点执行PCA

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() std_df = scaler.fit_transform(df) std_df.shape

找到协方差矩阵,即AT * A,使用NumPy的matmul方法。乘法之后,协方差矩阵的维度是784 * 784。

covar_mat = np.matmul(std_df.T, std_df) covar_mat.shape

找到两个最大的特征值和对应的特征向量,以便投影到2D表面。参数‘eigvals’定义(从低值到高值),eigh函数将按升序返回特征值,此代码仅生成最大的两个(782和783)特征值。

from scipy.linalg import eigh values, vectors = eigh(covar_mat, eigvals = (782, 783)) print("Dimensions of Eigen vector:", vectors.shape) vectors = vectors.T print("Dimensions of Eigen vector:", vectors.shape)

如果将两个最大的向量乘以协方差矩阵,找到了两个主成分PC1和PC2。

final_df = np.matmul(vectors, std_df.T) print("vectros:", vectors.shape, "n", "std_df:", std_df.T.shape, "n", "final_df:", final_df.shape) final_dfT = np.vstack((final_df, label)).T dataFrame = pd.DataFrame(final_dfT, columns = ['pca_1', 'pca_2', 'label']) dataFrame sns.FacetGrid(dataFrame, hue = 'label', size = 8) .map(sns.scatterplot, 'pca_1', 'pca_2') .add_legend() plt.show()
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485