主成分分析解读处理维数的诅咒
机器学习中,我们经常要处理高维数据。但并非我们在模型中使用的所有特征实际上都与响应变量无关。希望我们的模型能够更好地学习并提供准确的结果,我们添加许多特征,这通常会导致我们称之为“ 维度诅咒 ”的问题,该问题指出:
随着特征或维度数量的增加,我们需要准确概括的数据量呈指数级增长。
为了克服这个问题,我们需要确定数据集中最重要的特征。一种用于从数据集中识别主要特征从而减少数据集的维数的方法是主成分分析(PCA)。
究竟什么是PCA?
PCA接受大量变量,使用这些变量之间的依赖关系更易于管理的、低维的形式表示它,而不会丢失太多信息。PCA是数据探索的良好工具,通常作为探索性数据分析(EDA)的一部分。
假设我们的数据集中有n个观察值和d个变量,我们希望作为EDA的一部分研究不同变量之间的关系。对于更大的d值,假设为60,我们得到d(d-1)/ 2个二维散点图。如此大量的图(在本例中为1770)使得确定特征之间的关系变得很困难。此外,这些2D图仅包含数据集中存在的所有信息的一小部分。
这时候就需要用到PCA了。PCA是一种特征提取技术—它以特定的方式组合输入变量,然后去掉“最不重要”的变量,同时保留所有变量中最有价值的部分(或主要成分)!
主要成分是什么?
主成分是数据集中原始特征的归一化线性组合。假设我们从d维向量开始并希望通过向下投影到k维子空间来总结它们,这样新的子空间的轴就指向数据的最大方差的方向。我们的最终结果是将原始向量投影到k方向,称为主成分(PC)。
图1:从100个城市的广告数据(ISLR)子集中获取的广告支出(1000s)和人口(10,000s)之间的关系图。蓝点表示平均值(μ)。从图中可以看出,第一主成分(绿色实线)方向具有最大数据方差,并且它还定义了最接近所有n个观测值的直线。第一主成分捕获特征中包含的大部分信息,使得第一主成分捕获的可变性越大,成分捕获的信息越大。
图2:广告数据子集(ISLR)中的第一和第二主成分。第二主成分的方向由蓝色虚线给出(图2)。它也是原始特征的线性组合,其捕获数据集中的剩余方差,使得第一和第二主成分之间的相关性为零,因此它们的方向彼此正交或垂直。
同样,对于数据集中的d个特征,我们可以构造多达d个不同的主成分。
但是我们需要多少主成分?
选择正确数量的主成分对于确保PCA有效至关重要。包含n个观察值和d个特征的数据集占min(n - 1,d)个不同的主成分。但是我们只对前几个足以解释数据集中大量变化的主成分感兴趣。
确定这一点的一种方法是查看累积解释的方差比,该方差比是成分数量的函数。scree plot描绘了该比值由每个主成分的说明。图的弯曲部分表示主成分的最佳数量。
图3:在LFW人脸识别数据集上的PCA之后的累积解释方差比。图3中所示的曲线量化了总数中的多少,200维方差包含在前n个分量中。例如,我们看到,面对前40个成分包含超过80%的方差,而我们需要大约150个成分来描述接近100%的方差。
在哪里使用PCA?
PCA已广泛用于许多领域,例如计算机视觉和图像压缩。它主要用于以下应用:
- 数据可视化: PCA允许您将高维对象可视化为低维图像。
- 偏最小二乘: PCA特征可以作为偏最小二乘线性模型的基础。
- 维度降低:降低特征维度,仅丢失少量信息。
- 异常值检测(提高数据质量):以较少的维度投影一组变量并突出显示无关的值。
PCA如何表述呢?
给定的矩阵X,其对应于n的观测与d特征,以及输入ķ , PCA的主要目的是将矩阵X分解成两个较小的矩阵,Z和W,使得X = ZW,其中z具有维度N * k和W的维度为k * d(见图4)。Z的每一行都是因素加载。W的每一行称为主成分。
图4:PCA将矩阵 X分解成两个较小的矩阵 Z和W。在PCA中,我们最小化以下目标函数的平方误差:
解决PCA有三种常见方法,我们将在下面介绍。
1、奇异值分解(SVD)
这种方法首先使用奇异值分解(SVD)算法求出正交W。然后使用正交W来计算Z如下。
2、交替最小化
这是一种迭代方法,可以在以下两种情况下交替使用:
- 固定Z,找到W的最优值
- 固定W,找到Z的最优值
3、随机梯度下降
这是一种迭代方法,适用于矩阵X非常大的情况。在每次迭代中,它选择一个随机的例子i并以j为特征更新W和Z
PCA的作用:减少特征
我们已经知道,根据定义,PCA消除了不太重要的特征,并帮助生成这些特征的可视化表示。让我们看看这在实践中如何真正应用于特征缩减问题。在本例中,我们将使用Iris数据集。
数据包含四个属性:萼片长度,萼片宽度,花瓣长度,三个物种的花瓣宽度,即Setosa,Versicolor,Virginica
from sklearn.decomposition import PCAfrom sklearn.datasets import load_irisdef plot_slice(X, tX, itX=None, axis_i=0, axis_j=1): """ Define a helper function. """ species = X.target n_plots = 2 if itX is not None: n_plots = 3 plt.figure(figsize=(4 * n_plots, 4)) plt.subplot(1, n_plots, 1) plt.title('Data') plt.plot(X.data[species == 0, axis_i], X.data[species == 0, axis_j], "o