详解主成分分析PCA与奇异值分解SVD-高维数据可视化以及参数n_components【菜菜的sklearn课堂笔记】

时间:2022-11-14 16:13:45

视频作者:菜菜TsaiTsai 链接:【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili

高维数据的可视化和n_components

PCA(
    ['n_components=None', 'copy=True', 'whiten=False', "svd_solver='auto'", 'tol=0.0', "iterated_power='auto'", 'random_state=None'],
)
# n_components:降维后维度的数量,可填正整数、[0,1]浮点数、mle
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import pandas as pd

iris = load_iris()
X = iris.data
y = iris.target
X.shape
---
(150, 4)

pd.DataFrame(X).head()
---
	0	1	2	3
0	5.1	3.5	1.4	0.2
1	4.9	3.0	1.4	0.2
2	4.7	3.2	1.3	0.2
3	4.6	3.1	1.5	0.2
4	5.0	3.6	1.4	0.2

set(y)
---
{0, 1, 2}

pca = PCA(n_components=2) # 实例化
# 这里n_components=2,就是说降维以后需要留下2个维度的特征
pca = pca.fit(X) # 拟合模型
X_dr = pca.transform(X) # 获取新矩阵
# 也可以一步到位 X_dr = PCA(2).fit_transform(X)
X_dr[:5,:]
---
array([[-2.68412563,  0.31939725],
       [-2.71414169, -0.17700123],
       [-2.88899057, -0.14494943],
       [-2.74534286, -0.31829898],
       [-2.72871654,  0.32675451]])

plt.figure()
plt.scatter(X_dr[y==0,0], X_dr[y==0,1],c="red",label=iris.target_names[0],alpha=0.7)
plt.scatter(X_dr[y==1,0], X_dr[y==1,1],c="black",label=iris.target_names[1],alpha=0.7)
plt.scatter(X_dr[y==2,0], X_dr[y==2,1],c="orange",label=iris.target_names[1],alpha=0.7)
# alpha:透明度
plt.legend()
plt.title("PCA of IRIS dataset")
plt.show() # 降维后数据可视化

详解主成分分析PCA与奇异值分解SVD-高维数据可视化以及参数n_components【菜菜的sklearn课堂笔记】

pca.explained_variance_
# 属性explained_variance_,查看降维后每个新特征向量上所带的信息量大小(可解释方差的大小)
# 往往第一个特征上信息量最大,即方差最大,向后逐渐减小
---
array([4.22824171, 0.24267075])

pca.explained_variance_ratio_
# 属性explained_variance_ratio_,查看将为后每个新特征向量所占的信息量和原始数据总信息量的百分比
# 又叫可解释方差贡献率
# 大部分信息都被有效的集中在了第一个特征上
---
array([0.92461872, 0.05306648])

pca.explained_variance_ratio_.sum() # 新矩阵带有原矩阵的数据量
---
0.977685206318795

pca_line = PCA().fit(X) # 默认返回min(X.shape)个特征
pca_line.explained_variance_ratio_
# 因为对协方差矩阵进行分解后就可以得到最优的p个方向向量
# 将数据代入求解即可以得到每个方向上数据的方差占比
---
array([0.92461872, 0.05306648, 0.01710261, 0.00521218])

选择最好的n_components:累积可解释方差贡献率曲线 在数据量大于特征维度的时候,我们设置n_components为默认值,可以画出累计可解释方差贡献率曲线,以此选择最好的n_components的整数取值。 累积可解释方差贡献率曲线是一条以降维后保留的特征个数为横坐标,降维后新特征矩阵捕捉到的可解释方差贡献率为纵坐标的曲线,能够帮助我们决定n_components最好的取值。

import numpy as np

plt.figure()
plt.plot([1,2,3,4],np.cumsum(pca_line.explained_variance_ratio_))
plt.xticks([1,2,3,4])
plt.xlabel("number of components after dimension reduction") # 降维后维度数量
plt.ylabel("cumulative explained variance ratio") # 累计可解释方差比

详解主成分分析PCA与奇异值分解SVD-高维数据可视化以及参数n_components【菜菜的sklearn课堂笔记】

一般这条曲线会先急剧上升,然后平缓上升至1,我们选择急剧到平缓转折点对应的数值作为n_components的值

最大似然估计自选超参数

最大似然估计选择超参数是让PCA自选超参数的方法。需要注意的是,该方法计算量较大,在高维度时会消耗大量时间

pca_mle = PCA(n_components='mle')
pca_mle = pca_mle.fit(X)
X_mle = pca_mle.transform(X)
X_mle.shape # MLE自动选择了三个特征
---
(150, 3)

按信息量占比选超参数

n_components后面加$[0,1]$之间的浮点数,并且让数svd_solver ='full',表示希望降维后的总解释性方差占比大于n_components指定的百分比。比如说,如果我们希望保留97%的信息量,就可以输入n_components=0.97,PCA会自动选出能够让保留的信息量超过97%的特征数量。

pca_f = PCA(n_components=0.97,svd_solver="full")# 浮点数指定降维后携带的信息量
pca_f = pca_f.fit(X)
X_f = pca_f.transform(X)
pca_f.explained_variance_ratio_
---
array([0.92461872, 0.05306648])

pca_f.explained_variance_ratio_.sum()
---
0.977685206318795

pca_f = PCA(n_components=0.99,svd_solver="full")
pca_f = pca_f.fit(X)
X_f = pca_f.transform(X)
pca_f.explained_variance_ratio_.sum()
---
0.9947878161267247

svd_solver

PCA(
    ['n_components=None', 'copy=True', 'whiten=False', "svd_solver='auto'", 'tol=0.0', "iterated_power='auto'", 'random_state=None'],
)
# svd_solver:在降维过程中,用来控制矩阵分解的一些细节的参数。有四种模式可选:"auto", "full", "arpack", "randomized",默认”auto"。

"auto":基于X.shape和n_components的默认策略来选择分解器。如果输入数据的尺寸大于500x500且要提取的特征数小于数据最小维度min(X.shape)的80%,就启用效率更高的”randomized“方法。否则,精确完整的SVD将被计算,截断将会在矩阵被分解完成后有选择地发生

"full":从scipy.linalg.svd中调用标准的LAPACK分解器来生成精确完整的SVD,适合数据量比较适中,计算时间充足的情况,生成的精确完整的SVD的结构为: $$ U_{m,m}\Sigma_{m,n}V_{n,n}^{T} $$

"arpack":从scipy.sparse.linalg.svds调用ARPACK分解器来运行截断奇异值分解(SVD truncated),分解时就将特征数量降到n_components中输入的数值k,可以加快运算速度,适合特征矩阵很大的时候,但一般用于特征矩阵为稀疏矩阵的情况,此过程包含一定的随机性。截断后的SVD分解出的结构为: $$ U_{m,k}\Sigma_{k,k}V_{n,k}^{T} $$

不太理解这里的k是降维后的维度,还是去掉奇异值为0后奇异值的数量

"randomized",通过Halko等人的随机方法进行随机SVD。在"randomized"方法中,分解器会先生成多个随机向量,然后一一去检测这些随机向量中是否有任何一个符合我们的分解需求,如果符合,就保留这个随机向量,并基于这个随机向量来构建后续的向量空间。这个方法已经被Halko等人证明,比"full"模式下计算快很多,并且还能够保证模型运行效果。适合特征矩阵巨大,计算量庞大的情况。

random_state

而参数random_state在参数svd_solver的值为"arpack" or "randomized"的时候生效,可以控制这两种SVD模式中的随机模式。通常我们就选用”auto“,不必对这个参数纠结太多。