降维算法中的”降维“,指的是降低特征矩阵中特征的数量。
降维的目的是
1 为了让算法运算更快,效果更好,
2 还有另一种需求:数据可视化。(三维及以下的特征矩阵,是可以被可视化的,这可以帮助我们很快地理解数据的分布,而三维以上特征矩阵的则不能被可视化,数据的性质也就比较难理解)
在高维数据中,必然有一些特征是不带有有效的信息的(比如噪音),或者有一些特征带有的信息和其他一些特征是重复的(比如一些特征可能会线性相关)。
我们希望能够找出一种办法来帮助我们衡量特征上所带的信息量,让我们在降维的过程中,能够即减少特征的数量,又保留大部分有效信息——将那些带有重复信息的特征合并,并删除那些带无效信息的特征等等——逐渐创造出能够代表原特征矩阵大部分信息的,特征更少的,新特征矩阵。
在降维中,PCA使用的信息量衡量指标,是样本方差,又称可解释性方差,方差越大,特征所带的信息量越多。
Var代表一个特征的方差,n代表样本量,xi代表一个特征中的每个样本取值,xhat代表这一列样本的均值。
参数:
class sklearn.decomposition.PCA (n_components=None, copy=True, whiten=False, svd_solver=’auto’, tol=0.0,
iterated_power=’auto’, random_state=None)
2维降1维例子
n维特征矩阵降维步骤:
1 输入原数据,结构为 (m,n),找出原本的n个特征向量构成的n维空间,
2 决定降维后的特征数量:k,
3 通过某种变化,找出n个新的特征向量,以及它们构成的新n维空间,
4 找出原始数据在新特征空间V中的n个新特征向量上对应的值,即“将数据映射到新空间中”
5 选取前k个信息量最大的特征,删掉没有被选中的特征,成功将n维空间V降为k维
降维和特征选择都是特征工程技术,它们有什么不同?
特征选择是从已存在的特征中选取携带信息最多的,选完之后的特征依然具有可解释性,我们依然知道这个特征在原数据的哪个位置,代表着原数据上的什么含义
而降维算法 是将已存在的特征进行压缩,降维完毕后的特征不是原本的特征矩阵中的任何一个特征,而是通过某些方式组合起来的新特征。通常来说,在新的特征矩阵生成之前,我们无法知晓降维算法们都建立了怎样的新特征向量,新特征矩阵生成之后也不具有可读性
PCA一般不适用于探索特征和标签之间的关系的模型(如线性回归),因为无法解释的新特征和标签之间的关系不具有意义。在线性回归模型中,我们使用特征选择。
n_components是我们降维后需要的维度,即降维后需要保留的特征数量,降维流程中第二步里需要确认的k值,
应用鸢尾花数据集:
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
iris=load_iris()
X=iris.data
y=iris.target
X.shape,y.shape
((150, 4), (150,))
import pandas as pd
pd.DataFrame(X)
y
#调用pca
pca = PCA(n_components=2) #实例化
pca = pca.fit(X) #拟合模型
X_dr = pca.transform(X) #获取新矩阵
#X_dr=PCA(n_components=2).fit_transform(X)
X_dr.shape#降维2维了 #(150, 2)
X_dr[y==0,0] #布尔索引,y==0代表第一个标签,0代表第一个特征(0列)
plt.figure()
plt.scatter(X_dr[y==0,0],X_dr[y==0,1],c='red',label=iris.target_names[0])
plt.scatter(X_dr[y==1, 0], X_dr[y==1, 1], c="black", label=iris.target_names[1])
plt.scatter(X_dr[y==2, 0], X_dr[y==2, 1], c="orange", label=iris.target_names[2])
plt.legend()
plt.title('PCA of IRIS dataset')
plt.show()
4 选择最好的n_components:累积可解释方差贡献率曲线
当参数components中不填写任何值,则默认返回min(X.shape)个特征,没有减少特征的个数,不会使用这种输入方式。但我们却可以使用这种输入方式来画出累计可解释方差贡献率曲线,以此选择最好的n_components的整数取值。
累积可解释方差贡献率曲线是一条以降维后保留的特征个数为横坐标,降维后新特征矩阵捕捉到的可解释方差贡献率为纵坐标的曲线,能够帮助我们决定n_components最好的取值。
'''
pca.explained_variance_#c查看降维后每个新特征向量所带信息量大小(可解释性方差)
pca.explained_variance_ratio_ #查看降维后每个新特征向量所占信息量占原始信息百分比
pca.explained_variance_ratio_ .sum()# 查看降维后每个新特征向量所占信息量占原始信息百分比的总和
'''
import numpy as np
pca_line = PCA().fit(X)
plt.plot([1,2,3,4],np.cumsum(pca_line.explained_variance_ratio_))#np.cumsum分别取前i项的和
plt.xticks([1,2,3,4]) #这是为了限制坐标轴显示为整数[1,2,3,4]
plt.xlabel("number of components after dimension reduction")
plt.ylabel("cumulative explained variance ratio")
plt.show()
输入“mle”作为n_components的参数输入,就可以调用这种方法
注意:这种方法计算量较大,如果数据十分大,可能会崩
pca_mle = PCA(n_components="mle")
pca_mle = pca_mle.fit(X)
X_mle = pca_mle.transform(X)
X_mle
#可以发现,mle为我们自动选择了3个特征
pca_mle.explained_variance_ratio_.sum()
#得到了比设定2个特征时更高的信息含量,对于鸢尾花这个很小的数据集来说,3个特征对应这么高的信息含量,并不需要去纠结于只保留2个特征,毕竟三个特征也可以可视化
输入[0,1]之间的浮点数,并且让参svd_solver ==‘full’,表示希望降维后的总解释性方差占比大于n_components指定的百分比,即是说,希望保留百分之多少的信息量
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_.sum()
0.977685206318795
“auto” 通常选用
“full” 适用数据量比较居中,计算时间充足的情况
“arpack” 适合特征矩阵稀疏
“randomized” 适合特征矩阵巨大,计算量大