主成分分析Principal component analysis(PCA)
“主成分分析(PCA)是一种经典的无参降维算法,通过线性变换将高维数据投影到低维空间,以消除维度共线性并最大化保留数据方差。尽管降维后的主成分缺乏业务可解释性,但能有效简化模型。在Python实战中,常利用scikit-learn库结合方差阈值动态选择主成分数量,是机器学习建模前核心的数据预处理步骤。”
深入理解主成分分析(PCA):从原理到 Python 实战
为什么需要降维?
在面对海量数据或大数据进行数据挖掘时,通常会面临**“维度灾难”**。原因是数据集的维度可以不断增加而无穷多,但计算机的处理能力和速度却不是无限的。
另外,数据集的大量维度之间可能存在共线性的关系,这会直接导致学习模型的健壮性不够,甚至很多时候会失效。因此,我们需要一种可以降低维度数量并降低维度间共线性影响的方法——这就是降维的意义所在。
什么是主成分分析(PCA)?
主成分分析(Principal Component Analysis,简称 PCA),也称主分量分析,是一种经典的降维方法。它旨在利用降维的思想,把多维指标转化为少数几个综合维度,然后利用这些综合维度进行数据挖掘和学习,以代替原来利用所有维度进行挖掘学习的方法。
基本原理与数学变换
主成分分析的基本方法是按照一定的数学变换方法,把给定的一组相关变量(维度)通过线性变换转成另一组不相关的变量,这些新的变量按照方差依次递减的顺序排列。
在数学变换中,PCA 保持变量的总方差不变:
- 第一主成分:使第一变量具有最大的方差。
- 第二主成分:方差次大,并且和第一变量不相关。
- 依次类推:如果原始有 $I$ 个变量,就会有 $I$ 个主成分。
PCA 降维结果解析
到底主成分分析的结果是怎样的状态?下面简单举一个例子。
假设原始数据集中有 10 个维度,分别是 tenure、cardmon、lncardmon、cardten、lncardten、wiremon、lnwiremon、wireten、lnwireten、hourstv。现在用主成分分析进行降维,降维后提取出 5 个能代表原始 10 个维度的新“维度”(即主成分),每个“因子”的方程式如下:
code
结果的业务可解释性
通过上述结果我们可以发现,主成分(也就是新的“维度”)是一个多元一次的线性方程。
其含义是无法被人类直接理解的,这意味着人类无法将特征提取的方法直接应用到主成分分析之上(在类似于特征提取或分类器的算法中,可以直接了解原始参与计算的每个维度的权重的高低)。
核心观点:但这没有关系,因为机器学习或数据挖掘不需要知道每个因子的具体含义,只需要知道用哪些因子、如何计算,便能得到最终结果。
PCA 的优缺点分析
- 优点(降维与无参性):PCA 可以对主成分分析的结果按重要性排序,并根据用户需求只选择能代表大多数(甚至全部)指标意义的成分,从而达到降维、简化模型或是进行数据压缩的效果。另外,它是完全无参数限制的,这意味着无需人为设定参数,且不需要先验经验,实用性和推广性非常强。
- 缺点(缺乏人工干预):这个优点从另一个角度讲却是个缺点。因为它忽略了对具有先验经验的人群和应用场景的优化,导致某些场景下缺少一定“高效果”的人工干预,从而可能无法达到预期效果。
Python 机器学习实战:使用 scikit-learn
下面应用一个案例,用 Python 的机器学习库 sklearn 中的 PCA 来对数据进行降维。原始数据集中有 4 个维度,现在要通过 PCA 转换成 2 个维度。
代码实现
python
运行结果
降维后的原始数据集中的 4 个维度被转化成 2 个维度,结果如下:
code
实战技巧:如何选择主成分数量?
PCA 应用的关键是找到能代表原始数据最大特征的几个主成分。
在上述代码中,可以通过 pca.explained_variance_ratio_ 来查看每个主成分能表达原始数据的方差。实际应用时,可写一个循环来判定不同主成分数量下的方差之和,同时配合一个阈值来选择 PCA 中 components 的个数。
例如:可设定能代表原始数据集 95% 方差的主成分即可。当循环出来的主成分的方差之和大于 95% 时就可以停止循环,然后进行接下来的数据处理工作。
参数配置与应用场景
PCA 可配置的核心参数如下:
python
应用场景: 如本文开篇所述,PCA 的核心应用是降维。它通常用在所有大量数据集建模处理之前的降维过程,因此它是数据预处理中至关重要的一步。
尾声:直观理解 PCA 的空间投影
从主观的理解上,主成分分析到底是什么?
它其实是对数据在高维空间下的一个投影转换,通过一定的投影规则将原来从一个角度看到的多个维度映射成较少的维度。到底什么是映射?下面的图就可以很好地解释这个问题:正常角度看是两个半椭圆形分布的数据集,但经过旋转(映射)之后,变成了两条线性分布的数据集。
