降维之主成分分析(PCA)

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第21天,点击查看活动详情

之前我介绍过了降维中常用的两种方法:投影和流形学习,现在看一下最流行的一种降维算法:PCA。

PCA

我们先看下图1:

图1 子空间投影

左图是一个很简单得二维得散点图,而右图就是从上到下分别是投射在细直线、虚线和点线(三条线也就是三个不同的轴)上的图像。右边每个图上的存在很大的差异,图像的范围从大到小,但是都是存在一定程度的实例的丢失。

我们需要做的就是,找到在原始数据集与其所在的轴上的投影之间的均方距离最小的轴,

主要成分

主成分分析,就是识别出哪条轴的贡献度高。需要注意的是轴的数量和数据集维度数量相同(如上图有两个箭头,就是找到的两个主要成分)。因此我们也称第i个轴为数据的第i个主要成分。

那么我们该怎么去找到这些主要成分呢?这里需要使用一种叫奇异值分解(Singular Value Decomposition,SVD)的标准矩阵分解技术。它会将原本的数据集矩阵X分解成有三个矩阵 U Σ V T U \Sigma V^{T} 的矩阵乘法。而我们需要的所有的主要成分的单位向量正好在 V V 中。

因此我们也可以使用Numpy的svd()获取训练集的所有主成分。

U, s, Vt=np.linalg.svd(X) 比如现在只有二维,那我们只需要通过Vt的转置矩阵的前两列就行。

向下投影到d维度

当我们知道了主要成分,我们是不是就可以将原本的数据集投影到由前n个主要成分定义的超平面上,完成数据集的维度降低到d维。当然别忘了要选择尽可能多的保留原始数据集特征的那一个主要成分哦。

这边设我们将原本的数据集降维后的简化矩阵维 X d X_{d} ,那么它与原本数据集 X X 的关系如下:

X d = X W d X_{d}=XW_{d}

其中的 W d W_{d} 就是之前的 V V 中前n列的矩阵。例如我们要将降到2维:

  1. W_{2} = Vt.T[:,:2]
  2. X2d=X.dot(W2)

哦对了,这里需要注意一下,我们的数据集 X X 最好是居中的,我们可以按照X-X.mean(axis=0)将其居中。现在我们已经实现了能够将任何数据集降维到任何数量的维度。当然我们也可直接使用Scikit-Learn中的PCA()

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
X2D = pca.fit_transform(X)
复制代码

n_components就是我们设置需要降低到多少维度,同时PCA()可以自动处理数据居中问题。同时pca中还有 W d W_{d} 的转置矩阵放在components_中,我们只需要访问pca.components_.T[:.0]获得。

选择正确的维度

接下来我们就需要选择尽可能比较好的维度去替代原本数据集完成任务。在这里我们需要先了解一个叫可解释方差比的参数-explained_variance_ratio:他表示的沿着每个成分的数据集方差的比率。也就是他会返回每个不同的PC上数据集的方差比率,我们要找的比例越高越好。

刚才使用了n_components用于表示降维的维数,当然我们也可以设置0.0-1.0之间的浮点数,表示需要的数据集方差的比率如pca = PCA(n_components=0.95),就是需要方差率在95%的。

我们也可以看一下有方差率绘制的函数图像去判断需要怎么样的方差率:

图2 方差函数图像

我们可以看到方差一开始增加的很快,但是经过一个拐点后增加速度明显降低,因此在选择需要降低到多少维度比较合适时,也可以参照该图。这样我们可以尽可能地小的压缩,也不可以达到一个不错的效果。

当然如果我们获得一个压缩后的矩阵后,想要还原到原本的矩阵也可以使用inverse_transform()。不过由于之前压缩丢弃了一部分数据,解压时返回的矩阵也只能是尽可能的相似。

随机PCA

在PCA中有一种叫Randomized PCA的随机算法,能够很快的计算出前d个主成分的近似值。只需要设置PCA()的超参数svd_solver=randomized,如果在默认情况下,svd_solver=auto,当m或者n(矩阵的行和列)大于500,d小于m或n的80%时,Scikit-Learn也会自动使用随机PCA算法。

增量PCA

不知道读者是否还记得增量学习,就是可以将原本的大量的数据分成多个少量数据进行训练。如果使用PCA()他使得我们必须将整个数据集装入内存,但是同时也有增量PCA。使用起来也很方便:

inc_pca = IncrementalPCA(n_components=154)
for X_batch in np.array_split(X_train, n_batches):
    # 按照n_batches数量切割数据集后放入IncrementalPCA()中
    inc_pca.partial_fit(X_batch)
复制代码

谢谢各位阅读,今日学习PCA到这就完了,舒服!

猜你喜欢

转载自juejin.im/post/7109113364411842573