主成分分析 (principal component analysis, PCA) 是投影法的典型代表。投影法是指将高维的数据向低维投影,投影的方向可通过特征值分析等方法来确定。
具体来说,假设我们有一个具有 (n) 维特征的数据集,共有 (m) 个样本点,我们希望这 (m) 个样本的特征维度从 (n) 降维到 (n') 维,希望这 (n') 维的数据集尽可能地代表原始数据集。
PCA 的几个注意点:
(1)原始数据中有多少个特征维度(变量),就会提取出多少个主成分。第一主成分包含了原始数据中最多的信息,第二个主成分包含了第二多的信息,依次递减。主成分之间互相线性无关;
(2)选择保留多少个主成分,取决于前 n 个主成分的累计方差占比(累计贡献率)。一般来说,必须保证的前几个主成分的累积贡献率在较高水平((ge85\%));
(3)提取的主成分个数应明显少于原始特征的个数,否则降维带来的利可能还抵不过信息量损失的弊。
算法过程
(1)对变量进行 Z-Score 标准化操作,消除变量间量纲不同造成的影响。
(2)计算数据的协方差矩阵。
(3)计算所得协方差矩阵的特征值(即主成分方差)和特征向量。
(4)将所得特征值从大到小排序,并选择最大的 k 个特征值(即前 k 个主成分)对应的特征向量。具体 k 如何选择,需要计算前 k 个特征值的累积贡献率来决定。
(5)将原始数据投影到所选取的 k 个特征向量组成的低维空间中,转化为新的样本。通过将原始数据乘以这 k 个特征向量即可得到。
算法的优缺点
优点:
(1)计算方法简单,易于实现。
(2)可消除原始变量之间的相关影响,因为主成分分析法在对原始数据变量进行变换后形成了彼此独立的主成分,而且实践证明变量间相关程度越高,主成分分析效果越好。
缺点:
(1)主成分的解释器含义一般多少带有一点模糊性,不像原始变量的含义那么清楚、确切。
(2)方差小的主成分也可能含有对样本差异的重要信息,丢弃后可能会对后续数据处理有不利影响。
PCA 与线性回归的区别
主成分分析最小化的是投射误差(Projected Error),而线性回归尝试的是最小化预测误差。线性回归的目的是预测结果,而主成分分析不作任何预测。
上图中,左边的是线性回归的误差(垂直于横轴投影),右边则是主成分分析的误差(垂直于红线投影)。
PCA 的变种
传统主成分分析存在一些局限性,如数据必须放在内存中计算,不适合处理非线性数据等,因此也出现了很多 PCA 的变种。
增量主成分分析
传统主成分分析需要将全部数据放入内存进行计算。对于很大的数据集,这种方法并不现实。我们可以将数据分成若干小分,每次只对其中的一份进行计算。这种方法就是增量主成分分析,除了可以用来处理大数据集,也方便在线处理。
随机主成分分析
随机主成分分析采用随机算法,近似计算主成分。当选取的主成分数远小于原始特征数时,可以较大程度提高运算速度。
核主成分分析
为了更好地处理非线性数据,我们可以引入非线性映射将原始数据先投射到高维特征空间,再在这个高维特征空间中实施 PCA。
PCA 的应用建议
一个常见错误使用主要成分分析的情况是, 将其用于减少过拟合(减少了特征的数量)。这样做非常不好,不如尝试正则化处理。原因在于主要成分分析只是近似地丢弃掉一些特征, 它并不考虑任何与结果变量有关的信息, 因此可能会丢失非常重要的特征。然而当我们进行正则化处理时,会考虑到结果变量,不会丢掉重要的数据。
另一个常见的错误是, 默认地将主要成分分析作为学习过程中的一部分, 这虽然很多时候有效果,最好还是从所有原始特征开始,只在有必要的时候(算法运行太慢或者占用太多内存)才考虑采用主要成分分析。
Python-sklearn-PCA
PCA类的主要输入参数有以下几个:
- n_components:这个参数可以帮我们指定希望PCA降维后的特征维度数目。
- 最常用的做法是直接指定降维到的维度数目,此时n_components是一个大于等于1的整数。
- 也可以指定主成分的方差和所占的最小比例阈值,让PCA类自己去根据样本特征方差来决定降维到的维度数,此时n_components是一个(0,1]之间的数。
- 还可以将参数设置为"mle", 此时PCA类会用MLE算法根据特征的方差分布情况自己去选择一定数量的主成分特征来降维。
- 也可以用默认值,即不输入n_components,此时n_components=min(样本数,特征数)。
- whiten :判断是否进行白化。所谓白化,就是对降维后的数据的每个特征进行归一化,让方差都为1。对于PCA降维本身来说,一般不需要白化。如果你PCA降维后有后续的数据处理动作,可以考虑白化。默认值是False,即不进行白化。
- svd_solver:即指定奇异值分解SVD的方法,由于特征分解是奇异值分解SVD的一个特例,一般的PCA库都是基于SVD实现的。有4个可以选择的值:{‘auto’, ‘full’, ‘arpack’, ‘randomized’}。
- randomized一般适用于数据量大,数据维度多同时主成分数目比例又较低的PCA降维,它使用了一些加快SVD的随机算法。
- full则是传统意义上的SVD,使用了scipy库对应的实现。
- arpack和randomized的适用场景类似,区别是randomized使用的是scikit-learn自己的SVD实现,而arpack直接使用了scipy库的sparse SVD实现。
- 默认是auto,即PCA类会自己去在前面讲到的三种算法里面去权衡,选择一个合适的SVD算法来降维。一般来说,使用默认值就够了。
除了这些输入参数外,有两个PCA类的成员值得关注。
第一个是explained_variance_,它代表降维后的各主成分的方差值。方差值越大,则说明越是重要的主成分。
第二个是explained_variance_ratio_,它代表降维后的各主成分的方差值占总方差值的比例,这个比例越大,则越是重要的主成分。
Demo
PCA-Iris
使用 PCA 对 Iris 数据集进行降维。
Jupyter Notebook 链接为:PCA-Iris
PCA-MNIST
使用 PCA 对 MNIST 数据集进行图像压缩。
Jupyter Notebook 链接为:PCA-MNIST
【References】
[1] 裔隽,张怿檬,张目清等.Python机器学习实战 [M].北京:科学技术文献出版社,2018
[2] Andrew Ng. Machine Learning [EB/OL]. https://www.coursera.org/learn/machine-learning/home/info,2019-6-29