通过使用空模型比较,我将为您的问题添加更直观的答案。该过程随机地对每一列中的数据进行混洗,以保留总体方差,同时丢失变量(列)之间的协方差。这将执行几次,然后将随机矩阵中所得的奇异值分布与原始值进行比较。
我使用prcomp
而不是svd
进行矩阵分解,但是结果相似:
set.seed(1)
m <- matrix(runif(10000,min=0,max=25), nrow=100,ncol=100)
S <- svd(scale(m, center = TRUE, scale=FALSE))
P <- prcomp(m, center = TRUE, scale=FALSE)
plot(S$d, P$sdev) # linearly related
对以下居中矩阵执行空模型比较:
library(sinkr) # https://github.com/marchtaylor/sinkr
# centred data
Pnull <- prcompNull(m, center = TRUE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda[,1:20], ylim=range(Pnull$Lambda[,1:20], Pnull$Lambda.orig[1:20]), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=FALSE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)
以下是置换矩阵的箱线图,每个奇异值的95%分位数显示为实线。的PCA的原始值为m
点。它们都位于95%线以下-因此其幅度与随机噪声是无法区分的。
可以在的非中心版本上m
执行相同的步骤,结果相同-没有明显的奇异值:
# centred data
Pnull <- prcompNull(m, center = FALSE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda[,1:20], ylim=range(Pnull$Lambda[,1:20], Pnull$Lambda.orig[1:20]), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=TRUE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)
为了进行比较,让我们看一下具有非随机数据集的数据集: iris
# iris dataset example
m <- iris[,1:4]
Pnull <- prcompNull(m, center = TRUE, scale=FALSE, nperm = 100)
Pnull$n.sig
boxplot(Pnull$Lambda, ylim=range(Pnull$Lambda, Pnull$Lambda.orig), outline=FALSE, col=8, border="grey50", log="y", main=paste("m (center=FALSE); n sig. =", Pnull$n.sig))
lines(apply(Pnull$Lambda, 2, FUN=quantile, probs=0.95))
points(Pnull$Lambda.orig[1:20], pch=16)
在这里,第一个奇异值很重要,并且解释了超过92%的总方差:
P <- prcomp(m, center = TRUE)
P$sdev^2 / sum(P$sdev^2)
# [1] 0.924618723 0.053066483 0.017102610 0.005212184