维度对于数组来说就是shape值。比如array([1, 2, 3, 4])是一维,array([[1,2,3,4],[5,6,7,8]])是二维,array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])是三维数组
import numpy as np
arr1 = np.array([1,2,3,4])
arr1.shape # 结果是(4,)
arr2 = np.array([[1,2,3,4],[5,6,7,8]])
arr2.shape # 结果是(2, 4)
arr3 = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
arr3.shape # 结果是(2, 2, 3)
维度对于一个特征矩阵或者一个DataFrame而言,有多少列就有多少维(假设行是样本数,列是特征)。如下图表示4维数据:
降维算法对数据进行降维主要是运用在特征矩阵中,用来减少特征矩阵中的特征。其目的是为了让算法运算更快、效果更好。但是降维之后数据便不再可解释了。
本节主要学习sklearn中的降维算法,在sklearn中降维算法集成在decomposition模块中,
算法 | 描述 |
---|---|
主成分分析 | |
decomposition.PCA | 主成分分析(PCA) |
decomposition.IncrementalPCA | 增量主成分分析(IPCA) |
decomposition.KernelPCA | 核主成分分析(KPCA) |
decomposition.MiniBatchSparsePCA | 小批量稀疏主成分分析 |
decomposition.SparsePCA | 稀疏主成分分析(SparsePCA) |
因子分析 | |
decomposition.FactorAnalysis | 因子分析(FA) |
独立成分分析 | |
decomposition.FastICA | 独立成分分析的快速算法 |
字典学习 | |
decomposition.DictionaryLearning | 字典学习 |
decomposition.MiniBatchDictionaryLearning | 小批量字典学习 |
decomposition.dict_learning | 字典学习用于矩阵分解 |
decomposition.dict_learning_online | 在线字典学习用于矩阵分解 |
高级矩阵分解 | |
decomposition.LatentDirichletAllocation | 具有在线变分贝叶斯算法的隐含狄利克雷分布 |
decomposition.NMF | 非负矩阵分解(NMF) |
其他矩阵分解 | |
decomposition.SparseCoder | 稀疏编码 |
在众多降维算法中SVD算法和主成分分析PCA算法最为常见,也用的最多。
降维的目的就是为了减少特征的数量,这必然是要删除数据。因此,在降维的过程中必然也会造成信息的减少,从而影响模型的效果。故在降维的过程中既要减少特征的数量,又要保留大部分有效信息。在之前的写的文章(特征选择)中讲过一种“方差过滤”的特征选择方法。其思想就是计算特征的方差,若方差表示该特征的值不带有有效信息。而PCA算法使用的信息量衡量指标,就是样本方差,又称可解释性方差,方差越大,特征所带的信息量越多。
降维的过程:
- 确定原始数据的n个特征向量构成的n维空间V。
- 通过某种变化,找出n个新的特征向量,以及它们构成的新n维空间V。
- 找出原始数据在新特征空间V中的n个新特征向量上对应的值,即“将数据映射到新空间中”。
- 选取前k个信息量最大的特征,删掉没有被选中的特征,即将n维空间V降为k维。
在降维过程中,找出n个新特征向量,让数据能够被压缩到少数特征上并且总信息量不损失太多的技术称为矩阵分解。PCA和SVD是两种不同的降维算法,但都遵从上面的降维过程,只是两者的矩阵分解方法不一样,信息量的衡量指标不同而已。PCA使用方差作为信息量的衡量指标,并且特征值分解来找出空间V。降维时,通过一系列数学计算(比如说,产生协方差矩阵 1 n X X T \frac {1} {n}XX^T n1XXT)将特征矩阵 X X X分解为以下三个矩阵,其中 Q Q Q和 Q − 1 Q^{-1} Q−1是辅助的矩阵, Σ Σ Σ是一个对角矩阵(即除了对角线上有值,其他位置都是0的矩阵),其对角线上的元素就是方差。降维完成之后,PCA找到的每个新特征向量就叫做“主成分”,而被丢弃的特征向量被认为信息量很少, 这些信息很可能就是噪音。而SVD使用奇异值分解来找出空间V,其中 Σ Σ Σ也是一个对角矩阵,不过它对角线上的元素是奇异值,这也是SVD中用来衡量特征上的信息量的指标。 U U U和 V T V^{T} VT分别是左奇异矩阵和右奇异矩阵,也都是辅助矩阵。
PCA在sklearn中的实现:
class sklearn.decomposition.PCA(n_components=None,
copy=True, whiten=False,
svd_solver=’auto’, tol=0.0,
iterated_power=’auto’, random_state=None)
参数n_components是一个超参数,表示降维后保留的特征个数。设置n_components的参数有以下方法:
1、累计可解释方差贡献率曲线:使用默认值训练,然后累计可解释性方差贡献率(explained_variance_ratio_)来判断最合适的n_components值。
import numpy as np
# X是sklearn中的鸢尾花数据可以通过load_iris()加载。因为鸢尾花数据集有4个特征所以下面的画图的x轴设置为[1,2,3,4]
pca_line = PCA().fit(X)
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")
plt.show()
从图中可以看出特征为2个时可解释性方差贡献率就已经接近98%了。
2、使用最大似然估计自选超参数:即将n_components设置为mle(maximum likelihood estimation)
pca_mle = PCA(n_components="mle")
X_mle = pca_mle.fit_transform(X)
X_mle
#可以发现,mle为我们自动选择了3个特征
pca_mle.explained_variance_ratio_.sum()
# 可解释性方差贡献率累计达到0.9947878161267247
3、按信息量占比选超参数:输入[0,1]之间的浮点数,并且让参数svd_solver ==‘full’,表示希望降维后的总解释性方差占比大于n_components 指定的百分比,即是说,希望保留百分之多少的信息量。比如说,如果我们希望保留97%的信息量,就可以输入 n_components = 0.97,PCA会自动选出能够让保留的信息量超过97%的特征数量。
pca_f = PCA(n_components=0.97,svd_solver="full")
X_f = pca_f.fit_transform(X)
pca_f.explained_variance_ratio_
svd_solver是奇异值分解器的意思,而为什么在PCA中会有SVD的算法?因为PCA和SVD涉及了大量的矩阵计算,两者都是运算量很大的模型,但 SVD有一种惊人的数学性质,即是它可以不计算协方差矩阵,直接找出一个新特征向 量组成的n维空间,而这个n维空间就是奇异值分解后的右矩阵 V T V^T VT (所以讲解降维过程时,我们说”生成新 特征向量组成的空间V",并非巧合,而是特指奇异值分解中的矩阵 V T V^T VT )。传统的SVD矩阵分解是 X → U Σ V T X \to U \Sigma V^T X→UΣVT。不计算协方差矩阵的分解过程 X → V T X \to V^T X→VT,最后所得的 V T V^T VT具有如下性质: X d r = X ∗ V [ : k ] T X_{dr}=X*V[:k]^T Xdr=X∗V[:k]T,其中k表示降维后得到的维度。
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,适合数据量比较适中,计算时 间充足的情况 |
arpack | 从scipy.sparse.linalg.svds调用ARPACK分解器来运行截断奇异值分解(SVD truncated),分解时就 将特征数量降到n_components中输入的数值k,可以加快运算速度,适合特征矩阵很大的时候,但一般用于 特征矩阵为稀疏矩阵的情况 |
randomized | 通过Halko等人的随机方法进行随机SVD。在"full"方法中,分解器会根据原始数据和输入的 n_components值去计算和寻找符合需求的新特征向量,但是在"randomized"方法中,分解器会先生成多个 随机向量,然后一一去检测这些随机向量中是否有任何一个符合我们的分解需求,如果符合,就保留这个随 机向量,并基于这个随机向量来构建后续的向量空间。这个方法已经被Halko等人证明,比"full"模式下计算快 很多,并且还能够保证模型运行效果。适合特征矩阵巨大,计算量庞大的情况 |
参数random_state在参数svd_solver的值为"arpack" or "randomized"的时候生效,可以控制这两种SVD模式中的随机模式。