使用主成分分析(PCA)进行特征降维

主成分分析(PCA)

主成分分析(Principal Component Analysis)是一种无监督的降维算法。不同于线性判别分析(LDA),PCA不需要数据集中包含类别标签,其核心思想是将高维特征映射到新的空间后,按照新空间各个特征重要性有序选取坐标轴。新空间构建时,第一个坐标轴选取原始数据映射后方差最大的方向,后续坐标轴均保证与之前坐标轴正交的情况下方差最大,重复该过程直至新空间维度与原始特征数相等,或新空间维度数量达到降维需求。

从线性代数的角度来看,PCA实际上是对原始数据去除平均值后,求协方差矩阵,然后对其特征值进行排序,并根据这些特征值对应的特征向量构建新空间。

PCA的实现

Numpy

使用NumPy中的SVD实现一个简单的PCA:

import numpy as np
from random import randint


X = np.array([randint(-10, 10) for _ in range(40)]).reshape(5, 8)
X_centred = X - X.mean(axis=0)
U, sigma, V = np.linalg.svd(X_centred)

# find the first and the second principal component
c1 = V.T[:, 0]
c2 = V.T[:, 1]

# projecting down to 3 dimensions 
# by computing the dot product of 
# the X and the first 3 principal components
X3D = X_centred.dot(V.T[:, :3])

Scikit-Learn

在Scikit-Learn中,有可以直接使用的PCA类,使用前不需要对数据进行去除均值的处理:

from sklearn.decomposition import PCA


# projecting down to 3 dimensions
pca = PCA(n_components=3)
X3D = pca.fit_transform(X)

# check the first principal component
c1 = pca.components_.T[:, 0]

Spark

Spark的机器学习库MLlib提供了可以对RDD[Vector]型的数据进行降维的PCA类:

import org.apache.spark.mllib.feature.PCA
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.rdd.RDD

val data = sc.parallelize(Seq(
    Vectors.dense(1, 0, 0, 0, 1),
    Vectors.dense(1, 1, 0, 1, 0),
    Vectors.dense(1, 1, 0, 0, 0),
    Vectors.dense(1, 0, 0, 0, 0),
    Vectors.dense(1, 1, 0, 0, 0)))
val pca = new PCA(k=3).fit(data)
val projected = data.map(feat => pca.transform(feat))
print(projected.take(2).mkString)
// [0.5206573684395938,-0.4271322870657469,-0.7392387395392244]
// [-1.1529018904707837,-0.7155024798795673,-0.3985893027102969]
print(pca.pc)
/*
0.0                   0.0                     0.0                  
-0.7557893406837769   0.17214785894087992     -0.6317812811178025  
0.0                   -5.551115123125783E-17  0.0                  
-0.39711254978700694  -0.8876503388204472     0.2331919784075056   
0.5206573684395938    -0.4271322870657469     -0.7392387395392244
*/

解释方差占比

具体选取PCA之后的多少个维度构建降维后的低维空间呢?这其实取决于你希望PCA降维后的表示可以包含高维空间中的多少信息。用来衡量携带信息量的常用指标就是解释方差占比(explained variance ratio),其计算就是分别求出各个特征值占所有特征值总和的占比。各个框架的PCA实现中都会提供接口,比如在Scikit-Learn中调用:

# check the explained variance ratio
evr = pca.explained_variance_ratio_

在上面Spark的例子中,我们可以获得对应的3个维度的解释方差占比:

print(pca.explainedVariance)
// [0.6512522620920779,0.2236380402113374,0.12510969769658492]

这意味着,第一个主成分包含了65.13%的方差信息,第二个主成分包含了22.36%。假设降维的目标是保留至少75%的方差信息,那么只保留前两个主成分就够了。

维度选取

既然可以获取解释方差占比,那我们就可以直接通过占比进行降维时的维度选择。比如我们期望保留95%的方差,那就可以对原始数据进行维度不变的PCA,然后寻找累加的解释方差占比高于95%的最少特征数:

pca = PCA()
pca.fit(X)
cumsum = np.cumsum(pca.explained_variance_ratio_)
d = np.argmax(cumsum >= 0.95) + 1

在Scikit-Learn中,同样的操作只需要在n_components的设定时赋一个0到1的浮点数,就可以自动进行:

pca = PCA(n_components=0.95)
X_reduced = pca.fit_transform(X)

当然,也可以像K-means的k值选取一样,在解释方差占比的累加值的曲线图中寻找elbow点,作为降维时的维度选取依据。

数据复原

使用PCA可以在保留足够方差的前提下,显著降低原始数据的维度,因此PCA也可以被看作是一种压缩算法。在Scikit-Learn中,同样提供将低维数据还原为高维数据的方法:

X_recovered = pca.inverse_transform(X_reduced)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值