前言
本文重在介绍Python中sklearn库中的PCA算法的使用,主要对各个常用参数进行介绍说明,将不涉及或很少涉及其数学原理介绍,若想了解原理可关注以下文章:
sklearn中的PCA
sklearn中的PCA:sklearn.decomposition.PCA
- sklearn中的降维算法都包含在
sklearn.decomposition
矩阵分解模块中。
PCA的基本思想:PCA以样本方差(又称可解释性方差)作为信息量衡量指标,旨在将带有重复信息的特征合并,同时删除那些无效的噪声信息,也就是减少特征数量的同时,又尽量保留大部分有效信息,创造出可近似代表原特征矩阵的、特征更少的新特征矩阵。
基本使用
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
digits = load_digits() # 加载数据集
pca = PCA(n_components=32) # 创建对象
# 常用接口
pca.fit(digits.data) # 拟合数据
X_pca = pca.transform(digits.data) # 变换(降维)数据
X_pca = pca.fit_transform(digits.data) # 拟合数据并对数据进行降维, 也可以分开用接口.fit()和接口.transform()
X_inverse = pca.inverse_transform(X_pca) # 低维数据重新映射到原来的高维
# 常用属性
pca.explained_variance_ # 各主成分的解释方差
pca.explained_variance_ratio_ # 各主成分的解释方差比
pca.components_ # 右奇异矩阵
常用属性和接口
常用属性与接口:
.components_
:右奇异矩阵,该矩阵的各个行向量为新特征矩阵的各个主成分方向.explained_variance_
:各个主成分的解释方差,.explained_variance_ratio_
:各个主成分的解释方差比.inverse_transform()
:将降维后的低维数据重新映射到原来的高维空间
参数说明
PCA默认参数:
PCA(n_components=None, copy=True, whiten=False, svd_solver='auto',
tol=0.0, iterated_power='auto', n_oversamples=10,
power_iteration_normalizer='auto', random_state=None)
重要参数:
n_components
svd_solver
random_state
whiten
n_components
n_components:降维后的目标维度,即降维后要保留的特征数量,默认为None
,也就是默认返回 min(X.shape)
个特征
整数
:取值范围为 (0, 原维度]浮点数
:取值范围为 [0,1],且让参数svd_solver设置为`’full’,浮点数表示希望保留至少百分之多少的信息量'mle'
:最大似然估计法自选超参数
一般来说,样本量都会大于特征数目,所以什么都不填就相当于转换了新特征空间,但没有减少特征的个数。
图像相关代码如下:
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
plt.style.use('seaborn')
mpl.rcParams.update({'font.family': 'Microsoft YaHei'})
digits = load_digits()
pca = PCA().fit(digits.data)
plt.figure()
plt.plot([*range(1, digits.data.shape[1]+1)], np.cumsum(pca.explained_variance_ratio_), color='blue', alpha=0.7)
plt.scatter([*range(1, digits.data.shape[1]+1)], np.cumsum(pca.explained_variance_ratio_), s=15, c='red', edgecolor='white', linewidth=1, alpha=0.7)
plt.xlabel('保留特征个数')
plt.ylabel('总方差贡献率')
plt.title('累积可解释方差贡献率曲线')
plt.show()
上图中以手写数字数据集为例,当参数值为整数时,我们可以绘制如图所示的累积可解释方差贡献率曲线来确定超参数。
svd_solver & random_state
svd_solver:在降维过程中,用来控制矩阵分解的一些细节,默认为 'auto'
,该参数一般使用默认值,不必对这个参数纠结太多。
'auto'
:基于特征矩阵的形状和n_components的默认策略来选择分解器,即如果输入数据的尺寸大于500×500且要提取的特征数小于数据最小维度min(X.shape)的80%,就启用效率更高的’randomized’方法。否则,精确完整的SVD将被计算,截断将会在矩阵被分解完成后有选择地发生。'full'
:从scipy.linalg.svd中调用标准的LAPACK分解器来生成精确完整的SVD,适合数据量比较适中,计算时间充足的情况。完整的SVD结构为 U(m,m),Λ(m,n),V(n,n)TU_{(m,m)},Lambda_{(m,n)},V_{(n,n)}^T,其中原特征矩阵的大小为 (m, n)'arpack'
:从scipy.sparse.linalg.svds调用ARPACK分解器来运行截断奇异值分解(SVD truncated),分解时就将特征数量降到n_components中输入的数值k,也就是选取协方差矩阵中的前k个向量,可以加快运算速度,适合特征矩阵很大的时候,但一般用于特征矩阵为稀疏矩阵的情况,此过程包含一定的随机性。截断后的SVD分解出的结构为 U(m,k),Λ(k,k),V(n,n)TU_{(m,k)},Lambda_{(k,k)},V_{(n,n)}^T'randomized'
:通过Halko等人的随机方法进行随机SVD。在'full'
方法中,分解器会根据原始数据和输入的 n_components值去计算和寻找符合需求的新特征向量,但是在'randomized'
方法中,分解器会先生成多个随机向量,然后一一去检测这些随机向量中是否有任何一个符合我们的分解需求,如果符合,就保留这个随机向量,并基于这个随机向量来构建后续的向量空间。这个方法已经被Halko等人证明,比'full'
模式下计算快很多,且还能够保证模型运行效果。适合特征矩阵巨大,计算量庞大的情况。
random_state:在参数svd_solver的值为”arpack” or “randomized”的时候生效,可以控制这两种SVD模式中 的随机模式。
whiten
whiten:控制特征矩阵的白化,bool值,默认为False,目的是去掉特征之间的相关性,并将所有特征的方差归一化。
数据的白化即对数据进行零均质化和白化变换处理,所谓零均值化也就是将所有样本值减去其均值;白化变换有很多方法,但其主要在于消除各特征之间的相关性并将方差做归一化处理。
总结
sklearn中基本的PCA算法的使用较为简单,主要用于特征降维、高维数据可视化、样本噪音过滤等常见场景且拥有相对不错的效果,但由于现在的编程语言在大型矩阵的运算上都不是很擅长,因此PCA往往需要占用很大的算力资源,计算较为缓慢;此外,降维后得到主成分不具有可解释性,即PCA是将原始特征进行压缩,降维后得到的主成分与原始特征不同,是通过某种变换组合起来的新特征。通常来说,在新的特征矩阵生成之前,我们不知道PCA建立了哪些新特征向量,新特征矩阵生成之后也不具有可读性。因此PCA一般不适用于探索特征和标签之间的关系的模型(如线性回归),因为无法解释的新特征和标签之间的关系不具有意义。
参数选择:一般情况下我们自定义n_components参数,在数据量不大时可以选择’mle’用最大似然估计法来选择目标维度,但若数据量过大则可能跑不出来;此外,我们更常将其设置为整数,通过绘图来对该超参数进行选择,若想要保证总方差贡献率,则也可以设置为浮点数。此外,对于参数 svd_solver一般设置为'ayto'
,让算法自行判断使用randomized
或者full
即可,对于参数whiten,由于该参数只有两个值,不妨都试一下,但一般情况下设置为False即可。
Reference
- 菜菜的sklearn机器学习
- scikit-learn.org/stable/inde…