如何在 R 中使用 PCA 执行降维

机器算法验证 r 主成分分析
2022-02-09 00:35:56

我有一个大数据集,我想执行降维。

现在,无论我在哪里读到我都可以为此使用 PCA。但是,在计算/执行 PCA 之后,我似乎仍然不知道该怎么做。在 R 中,这很容易通过 command 完成princomp

但是计算出 PCA 后该怎么办?如果我决定要使用前主成分,我该如何精确地减少我的数据集?100

4个回答

我相信您在问题中遇到的问题涉及使用较少数量的主成分 (PC) 截断数据。对于这样的操作,我认为该函数prcomp更具说明性,因为它更容易可视化重建中使用的矩阵乘法。

首先,给出一个合成数据集,Xt执行 PCA(通常您会将样本居中以描述与协方差矩阵相关的 PC:

#Generate data
m=50
n=100
frac.gaps <- 0.5 # the fraction of data with NaNs
N.S.ratio <- 0.25 # the Noise to Signal ratio for adding noise to data

x <- (seq(m)*2*pi)/m
t <- (seq(n)*2*pi)/n

#True field
Xt <- 
 outer(sin(x), sin(t)) + 
 outer(sin(2.1*x), sin(2.1*t)) + 
 outer(sin(3.1*x), sin(3.1*t)) +
 outer(tanh(x), cos(t)) + 
 outer(tanh(2*x), cos(2.1*t)) + 
 outer(tanh(4*x), cos(0.1*t)) + 
 outer(tanh(2.4*x), cos(1.1*t)) + 
 tanh(outer(x, t, FUN="+")) + 
 tanh(outer(x, 2*t, FUN="+"))

Xt <- t(Xt)

#PCA
res <- prcomp(Xt, center = TRUE, scale = FALSE)
names(res)

在结果 或prcomp中,您可以看到 PC 的 ( res$x)、特征值 ( res$sdev) 提供有关每个 PC 大小的信息,以及载荷 ( res$rotation)。

res$sdev
length(res$sdev)
res$rotation
dim(res$rotation)
res$x
dim(res$x)

通过对特征值求平方,您可以得到每台 PC 解释的方差:

plot(cumsum(res$sdev^2/sum(res$sdev^2))) #cumulative explained variance

最后,您可以仅使用主要(重要)PC 创建数据的截断版本:

pc.use <- 3 # explains 93% of variance
trunc <- res$x[,1:pc.use] %*% t(res$rotation[,1:pc.use])

#and add the center (and re-scale) back to data
if(res$scale != FALSE){
	trunc <- scale(trunc, center = FALSE , scale=1/res$scale)
}
if(res$center != FALSE){
    trunc <- scale(trunc, center = -1 * res$center, scale=FALSE)
}
dim(trunc); dim(Xt)

您可以看到结果是一个稍微平滑的数据矩阵,过滤掉了小尺度特征:

RAN <- range(cbind(Xt, trunc))
BREAKS <- seq(RAN[1], RAN[2],,100)
COLS <- rainbow(length(BREAKS)-1)
par(mfcol=c(1,2), mar=c(1,1,2,1))
image(Xt, main="Original matrix", xlab="", ylab="", xaxt="n", yaxt="n", breaks=BREAKS, col=COLS)
box()
image(trunc, main="Truncated matrix (3 PCs)", xlab="", ylab="", xaxt="n", yaxt="n", breaks=BREAKS, col=COLS)
box()

在此处输入图像描述

这是一个非常基本的方法,您可以在 prcomp 函数之外执行:

#alternate approach
Xt.cen <- scale(Xt, center=TRUE, scale=FALSE)
C <- cov(Xt.cen, use="pair")
E <- svd(C)
A <- Xt.cen %*% E$u

#To remove units from principal components (A)
#function for the exponent of a matrix
"%^%" <- function(S, power)
     with(eigen(S), vectors %*% (values^power * t(vectors)))
Asc <- A %*% (diag(E$d) %^% -0.5) # scaled principal components

#Relationship between eigenvalues from both approaches
plot(res$sdev^2, E$d) #PCA via a covariance matrix - the eigenvalues now hold variance, not stdev
abline(0,1) # same results

现在,决定保留哪些 PC 是一个单独的问题——我不久前感兴趣的一个问题。希望有帮助。

这些其他答案非常好且详细,但我想知道您是否真的在问一个更基本的问题:一旦您拥有 PC,您会做什么?

每台 PC 都只是成为一个新变量。假设 PC1 占总变异的 60%,PC2 占 30%。由于这占总变异的 90%,您可以简单地将这两个新变量 (PC) 作为原始变量的简化版本。这意味着将它们拟合到模型中,如果您对此感兴趣的话。当需要解释您的结果时,您可以在与每台 PC 相关的原始变量的背景下进行。

对不起,如果我低估了问题的范围!

我相信您最初的问题源于对 PCA 在做什么有点不确定。主成分分析允许您识别样本中的主要变异模式。这些模式根据经验计算为样本协方差矩阵的特征向量(“载荷”)。随后,当您将原始样本投影到它们定义的空间(“分数”)中时,这些向量充当样本的新“坐标系”。与第个特征向量/变异模式/加载/主成分相关的变异比例等于其中是样本的原始维度(iλiΣk=1pλkpp=784在你的情况下)。[请记住,因为您的协方差矩阵是非负的,因此您将没有负特征值。] 现在,根据定义,特征向量彼此正交。这意味着它们各自的投影也是正交的,并且最初你有一个可能相关的变量样本,现在你有一个(希望显着)更小的线性独立样本(“分数”)。 λ

实际上,使用 PCA,您使用 PC 的投影(“分数”)作为原始样本的替代数据。您对分数进行所有分析,然后使用 PC 重建原始样本,以了解原始空间发生了什么(这基本上是Principal Component Regression)。显然,如果您能够有意义地解释您的特征向量(“加载”),那么您将处于一个更好的位置:您可以通过直接对该加载进行推断来描述该加载所呈现的变化模式下您的样本发生了什么,并且根本不在乎重建。:)

一般来说,“在计算 PCA 之后”你会做什么取决于你的分析目标。PCA 只是为您提供数据的线性独立子样本,该子样本在 RSS 重建标准下是最佳的。您可以将其用于分类或回归,或两者兼而有之,或者正如我所提到的,您可能想要识别样本中有意义的正交变化模式。

评论:我认为决定要保留的组件数量的最佳天真方法是将您的估计基于您希望在降维样本中保留的样本变化的某个阈值,而不仅仅是一些任意数字,例如。$loadings3, 100, 200。正如 user4959 解释的那样,您可以通过检查由生成的列表对象中的字段下的列表的相关字段来检查累积变化princomp

在进行 PCA 之后,您可以选择前两个组件并进行绘图。您可以使用 R 中的碎石图查看组件的变化。还可以使用带有 loadings=T 的汇总函数,您可以找到组件的特征变化。

您还可以查看此http://www.statmethods.net/advstats/factor.htmlhttp://statmath.wu.ac.at/~hornik/QFS1/principal_component-vignette.pdf

试着想想你想要什么。您可以从 PCA 分析中解释很多东西。

最好的阿比克语