主成分分析 – 实战教程

📅 发布时间:2026/7/9 7:13:37 👁️ 浏览次数:
主成分分析 – 实战教程
原文towardsdatascience.com/principal-component-analysis-hands-on-tutorial-3a451ff3d5db主成分分析或 PCA 是统计学家和机器学习从业者可用的最受欢迎的降维方法之一。在深入探讨这意味着什么之前让我们谈谈一些我们日常生活中使用此类方法的场景可能甚至不知道我们在这样做。搜索引擎当我们使用谷歌或其他网站来寻找问题的答案时它们并不是逐字匹配我们的搜索查询而是首先使用方法将我们的搜索复杂度简化为更小的部分然后进行搜索——简化复杂度可以带来更快的搜索结果这是通过降维来实现的。图像压缩你还记得你试图将图片上传到网站却发现图片超过了最大文件大小限制的时候吗在处理了随之而来的挫败感之后我们随后寻求像 Photoshop 这样的工具来减小图片的大小。Photoshop 或类似工具在底层执行的操作被称为降维。音乐音乐流媒体服务使用各种方法来减小正在流传输的音乐的大小以节省我们和他们自己的带宽和成本。实现这一目标的一种方法就是使用降维。PCA 作为一种统计分析方法已经存在了一段时间因此已经在各种帖子中进行了介绍。在这篇文章中我们不会回顾 PCA 背后的统计方法的细节而是将重点放在更现代的例子上这些例子读者今天可以更好地与之相关联并帮助学习者更直观地掌握这个主题。现在我们已经熟悉了使用案例让我们看看这些维度是什么以及它们是如何被降低的1. 什么是维度以及为什么要降低它在机器学习和统计分析的背景下给定数据集中的每个变量或特征可能被称为“维度”。例如如果一个机器学习模型的目的是预测房屋的价格使用邮政编码、面积、楼层数和卧室数这四个变量每个变量都被称为“维度”。“维度”指的是数据集中这些变量的数量在我们的例子中是四个。换句话说我们的例子被称为四维数据集。在我们上面的例子中我们不会太关心降低维度因为只有四个维度但在有更高维度的情况下降低维度变得更为重要。例如在自然语言处理NLP领域每个单词或标记可以被视为一个维度正如你可以想象的那样在一个足够大的文档中我们最终会得到成千上万的标记和结果维度。另一个例子是在计算机视觉CV领域处理图像。图像中的每个像素都可以被视为一个特征或维度。如果一个图像有 100x100 像素那么它最终会有 10,000 个维度。随着尺寸的增加降低维度变得更加重要。虽然在数据集中拥有更多的特征和维度代表了更多的信息但这也带来了成本因为它使得处理数据集变得更加复杂和昂贵。在这种情况下我们使用降维方法如 PCA来加速机器学习模型的计算并降低数据的复杂性即提高可解释性。接下来让我们看看 PCA 是如何降低维度的。2. PCA 是如何工作的使用任何降维方法的主要目标正如其名所示是在尽可能保持数据中可用信息的同时减少数据的维度。在数据集中变化最大的特征往往携带更多信息因此在这个上下文中信息可以被视为每个特征或组件的方差代表着数据的分布或分布情况。有了这些知识我们可以更好地理解 PCA 是如何工作的。PCA 通过将数据减少到其主成分来降低维度。因此我们可能从一个 1,000 维的空间数据集开始使用 PCA 减少到 10 维的空间。现在我们更好地理解了 PCA 的概念定义我们将通过三个表格数据、文本和图像的示例来了解 PCA 在实际中的应用。让我们开始吧3. 手动示例3.1. 表格数据对于第一个示例我们将利用来自 Scikit-Learn 的Iris 数据集这是最著名的实践数据集之一可在开源、商业可用的BSD 许可证下使用。这个数据集包括 3 种鸢尾花的花瓣和萼片长度共 150 行和 4 列。因此数据集是四维的。由于有四个维度人类无法想象这个数据集的空间表示但我们可以将维度减少到两个然后可视化转换后的数据集。我们将使用一些库这些库可以使用下面的代码块安装%%sh pip install numpy pandas scikit-learn scikit-image matplotlib gensim-q让我们先导入我们将用于此练习的包# import librariesimportnumpyasnpimportpandasaspdfromsklearn.datasetsimportload_irisfromsklearn.preprocessingimportStandardScalerfromsklearn.decompositionimportPCAimportmatplotlib.pyplotasplt%matplotlib inline接下来我们将加载数据集标准化数据并应用 PCA# load the datasetirisload_iris()Xiris.data yiris.target# standardize the datascalerStandardScaler()X_stdscaler.fit_transform(X)# apply pcapcaPCA(n_components2)principal_componentspca.fit_transform(X_std)注意我们选择了一个二维数据集其中我们确定了n_components。现在让我们创建一个包含我们上面创建的两个主成分的数据框然后可视化它。# dataframe of principal componentsprincipal_dfpd.DataFrame(dataprincipal_components,columns[PC1,PC2])final_dfpd.concat([principal_df,pd.DataFrame(y,columns[target])],axis1)# visualizationplt.figure(figsize(8,6))targets[0,1,2]colors[r,g,b]fortarget,colorinzip(targets,colors):indicesfinal_df[target]target plt.scatter(final_df.loc[indices,PC1],final_df.loc[indices,PC2],ccolor,s50)plt.legend(iris.target_names)plt.xlabel(Principal Component 1)plt.ylabel(Principal Component 2)plt.title(PCA of Iris Dataset)plt.show()https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/e85d7c1ead804629ede5157519494a3e.pngIris 数据集的主成分分析好吧现在我们有了数据集上方的二维表示但在从 4 维降低到 2 维的过程中我们失去了多少信息记住在这个上下文中我们将方差视为信息所以让我们看看当我们选择降低维度时有多少方差被解释。整个过程与我们上面所做的是非常相似的所以我会跳过解释每一个步骤但我已经在代码中添加了注释以便更容易地跟踪代码。整体过程是这样的我们首先选择主成分的数量为 4这是 Iris 数据集的原始特征计数然后计算四维数据集的方差。由于原始数据集有四个特征那么四维主成分将代表数据集中的原始方差。然后我们将逐个减少维度计算每一步的方差最后可视化结果以展示在每一步通过降维丢失了多少信息即方差。# load the datasetirisload_iris()Xiris.data# standardize the datascalerStandardScaler()X_stdscaler.fit_transform(X)# apply pca (keep all 4 features to see the original variance)pcaPCA(n_components4)pca.fit(X_std)# calculate explained variance ratio for each principal componentexplained_variancepca.explained_variance_ratio_# calculate cumulative explained variancecumulative_variancenp.cumsum(explained_variance)# visualizeplt.figure(figsize(6,4))plt.plot(range(1,len(cumulative_variance)1),cumulative_variance,markero,linestyle--,colorb)plt.title(Cumulative Explained Variance)plt.xlabel(Number of Principal Components)plt.ylabel(Cumulative Explained Variance)plt.grid()plt.show()https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f241a273fef118ac8a77eb8d9ce642f7.png各种主成分数量的累积解释方差这非常有趣我们可以看到从右上角开始四维解释了 100%的方差正如预期的那样因为这是 Iris 数据集原始特征的数量。当我们降低维度到 3 时我们可以解释大约 99%的方差而将维度降低到 3 和 2 时信息损失增加因为我们分别保持了大约 96%和 72%的原始方差。让我们看看 NLP 空间中的另一个例子。3.2. 文本词嵌入是单词的向量或数组表示。对于这篇帖子我们不需要完全理解这是如何实现的但我们只需要知道例如单词medium可以被一个数字数组表示。这几乎就像用不同的字母表书写一样——想象一个世界在那里我们不是用字母而是用数字来表示单词。让我们导入几个库并查看使用嵌入单词medium将看起来是什么样子。注意我们使用的是全球词表示向量GloVe这是来自斯坦福大学的一个 50 维预训练嵌入。# import librariesimportgensim.downloaderasapifromsklearn.decompositionimportPCAimportmatplotlib.pyplotasplt%matplotlib inline# load pre-trained word embeddingmodelapi.load(glove-wiki-gigaword-50)# 50-dimensional embeddings现在我们已经导入了必要的库让我们看看单词medium的嵌入是什么样的model[medium]https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0824144445436f987ca6cf91a9fcc06e.png使用 GloVe 嵌入的单词medium如预期这是一个包含 50 个数字的数组代表单词medium。这个数组对人类读者来说并没有太多意义但如果我们向模型提供这个嵌入并告诉模型我们使用了 GloVe 来创建嵌入那么模型就会理解我们的意思是medium这些嵌入是强大的工具使人类与机器之间的沟通成为可能。现在我们理解了这个概念让我们选择一组随机的单词将它们从 50 维减少到二维并可视化它们。# select 10 random wordswords[red,blue,green,yellow,purple,orange,pink,brown,black,white]word_vectors[model[word]forwordinwords]# apply pcapcaPCA(n_components2)componentspca.fit_transform(word_vectors)# visualize 2-dimensional embeddingsplt.figure(figsize(8,6))fori,wordinenumerate(words):plt.scatter(components[i,0],components[i,1])plt.annotate(word,(components[i,0],components[i,1]))plt.title(PCA of Word Embeddings)plt.xlabel(Principal Component 1)plt.ylabel(Principal Component 2)plt.show()https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/58466f7dda512a33d4c9ef262438f125.png将单词嵌入到二维空间如上图所示单词现在被减少到只有两个维度因此我们可以可视化它们。让我们再次看看当我们减少维度时会丢失多少信息。这个过程与我们上次做的是类似的所以让我们直接进入代码# reduce to 10 dimensionspca_10dPCA(n_components10)word_vectors_10dpca_10d.fit_transform(word_vectors)# explained variance ratioexplained_variance_ratio_10dpca_10d.explained_variance_ratio_# cumulative variancecumulative_variance_10dnp.cumsum(explained_variance_ratio_10d)# plotplt.figure(figsize(8,6))plt.plot(range(1,11),cumulative_variance_10d,markero,linestyle--,colorb)plt.title(Cumulative Explained Variance for 10 Principal Components)plt.xlabel(Number of Principal Components)plt.ylabel(Cumulative Explained Variance)plt.xticks(range(1,11))plt.grid()plt.show()https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/924875d3f445575723ae66f093a3e83a.png不同主成分数量的累积解释方差如预期当我们有 9 或 10 个维度时我们从右上角开始方差为 100%随着维度的减少方差持续下降直到只有一个维度时方差大约为 37%。看到我们的二维表示中主成分分析PCA帮助我们保持了约 51%的信息这令人印象深刻在下一节中我们将转向计算机视觉领域看看 PCA 如何减少图像的维度。3.3. 图像我们的最后一个例子是一个视觉例子。我们将从一个图像开始然后使用 PCA 减少其维度。最后我们将查看结果看看图像在视觉质量和尺寸上的变化。我使用的图片是一张由Carlos Lugo 在 Unsplash拍摄的冰淇淋杯子的照片。我们遵循的步骤与我们迄今为止所做的是非常相似的但这次我们将 PCA 方法应用于图像而不是文本。注意为了运行这段代码您需要首先从Unsplash下载图片并将其保存到您的当前工作目录中命名为icecream.jpg。然后代码将顺利运行。# import librariesimportnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.decompositionimportPCAfromskimageimportio,color# load the imageimageio.imread(icecream.jpg)# convert to gray scalegray_imagecolor.rgb2gray(image)# get the original size and shape of the image before any further changesoriginal_sizegray_image.size original_shapegray_image.shapeprint(fOriginal Image Size (number of pixels):{original_size})print(fOriginal Image Shape:{original_shape})# standardize and flatten the image, since pca requires a matrix (each row is a pixel and each column is a feature after flatenning)h,wgray_image.shape flat_imagegray_image-np.mean(gray_image,axis0)# pca down to 50 dimensionspcaPCA(n_components50)image_pcapca.fit_transform(flat_image)# get the size and shape of the dimensionality-reduced/transformed imagereduced_sizeimage_pca.sizepca.components_.size reduced_shapeimage_pca.shapeprint(fReduced Image Size (number of pixels, after PCA):{reduced_size})print(fReduced Image Shape (after PCA):{reduced_shape})https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/929a25bb4f6113b132ded6764caffc8a.png在进一步讨论之前让我们暂停一下因为这非常有趣。我们可以看到像素计数从原始图像的 18,438,054 下降到转换图像的 438,250这是通过 PCA 实现的在需要压缩图像以节省空间或加快计算的各种用例中PCA 可以非常有用。我们还可以在“形状”中看到原始图像有 3,506 个特征或维度我们将它们减少到 50从而实现了上述像素减少。但这会导致我们能够直观确认的图像质量损失吗让我们来对比一下# reconstruct the transformed image so that we can view it laterreconstructed_imagepca.inverse_transform(image_pca)# plot images side by sideplt.figure(figsize(12,6))# original imageplt.subplot(1,2,1)plt.imshow(gray_image,cmapgray)plt.title(Original Image)plt.axis(off)# transformed imageplt.subplot(1,2,2)plt.imshow(reconstructed_image,cmapgray)plt.title(Reconstructed Image (PCA))plt.axis(off)plt.show()https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/beaf1e0e1b3cd6340d4b61c47ae8c42f.png图片对比 – 左侧为原始图像由Carlos Lugo在Unsplash上发布右侧为转换版本这非常有趣你有没有尝试过减小图像的大小以便将其附加到电子邮件中或提交到申请中这正是它的作用。我们可以看到右侧的转换重构图像似乎比左侧的原始图像质量低。因此我们使用 PCA 减小了图像的大小但我们也为此付出了质量损失或我们称之为信息或“方差”的代价。让我们量化这种信息损失。# explained information/varianceexplained_variancepca.explained_variance_ratio_ cumulative_variancenp.cumsum(explained_variance)# plotplt.figure(figsize(8,6))plt.plot(range(1,len(cumulative_variance)1),cumulative_variance,markero,linestyle--,colorb)plt.title(Cumulative Explained Variance for PCA Components)plt.xlabel(Number of Principal Components)plt.ylabel(Cumulative Explained Variance)plt.grid()plt.show()https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/fe38b8d637ddcbe515b3d1c697225da2.png不同主成分数量的累积解释方差与之前的例子类似我们可以看到随着我们降低数据的维度信息通过方差来衡量是如何丢失的从 50 维时的 98%解释方差降低到只有 1 维时的 53%。结论在这篇文章中我们探讨了降维是什么以及它在文本应用如搜索优化、降低音乐流媒体和图像压缩的文件大小中的用例。然后我们介绍了主成分分析作为降维的一种流行方法并探讨了三个降维的实战示例。感谢阅读如果你觉得这篇文章有帮助请在 Medium 上关注我并订阅以接收我的最新文章除非另有说明所有图像均由作者提供。