如何使用自举法或蒙特卡洛方法确定重要的主要成分?


40

我对确定从主成分分析(PCA)或经验正交函数(EOF)分析得出的有效模式的数量感兴趣。我对将这种方法应用于气候数据特别感兴趣。数据字段是一个MxN矩阵,其中M是时间维度(例如天),N是空间维度(例如lon / lat位置)。我已经读过一种可能的引导方法来确定重要的PC,但是无法找到更详细的描述。到目前为止,我一直在使用North的经验法则(North 等人,1982)来确定该临界值,但是我想知道是否有更健壮的方法可用。

举个例子:

###Generate data
x <- -10:10
y <- -10:10
grd <- expand.grid(x=x, y=y)

#3 spatial patterns
sp1 <- grd$x^3+grd$y^2
tmp1 <- matrix(sp1, length(x), length(y))
image(x,y,tmp1)

sp2 <- grd$x^2+grd$y^2
tmp2 <- matrix(sp2, length(x), length(y))
image(x,y,tmp2)

sp3 <- 10*grd$y
tmp3 <- matrix(sp3, length(x), length(y))
image(x,y,tmp3)


#3 respective temporal patterns
T <- 1:1000

tp1 <- scale(sin(seq(0,5*pi,,length(T))))
plot(tp1, t="l")

tp2 <- scale(sin(seq(0,3*pi,,length(T))) + cos(seq(1,6*pi,,length(T))))
plot(tp2, t="l")

tp3 <- scale(sin(seq(0,pi,,length(T))) - 0.2*cos(seq(1,10*pi,,length(T))))
plot(tp3, t="l")


#make data field - time series for each spatial grid (spatial pattern multiplied by temporal pattern plus error)
set.seed(1)
F <- as.matrix(tp1) %*% t(as.matrix(sp1)) + 
as.matrix(tp2) %*% t(as.matrix(sp2)) + 
as.matrix(tp3) %*% t(as.matrix(sp3)) +
matrix(rnorm(length(T)*dim(grd)[1], mean=0, sd=200), nrow=length(T), ncol=dim(grd)[1]) # error term

dim(F)
image(F)


###Empirical Orthogonal Function (EOF) Analysis 
#scale field
Fsc <- scale(F, center=TRUE, scale=FALSE)

#make covariance matrix
C <- cov(Fsc)
image(C)

#Eigen decomposition
E <- eigen(C)

#EOFs (U) and associated Lambda (L) 
U <- E$vectors
L <- E$values

#projection of data onto EOFs (U) to derive principle components (A)
A <- Fsc %*% U

dim(U)
dim(A)

#plot of top 10 Lambda
plot(L[1:10], log="y")

#plot of explained variance (explvar, %) by each EOF
explvar <- L/sum(L) * 100
plot(explvar[1:20], log="y")


#plot original patterns versus those identified by EOF
layout(matrix(1:12, nrow=4, ncol=3, byrow=TRUE), widths=c(1,1,1), heights=c(1,0.5,1,0.5))
layout.show(12)

par(mar=c(4,4,3,1))
image(tmp1, main="pattern 1")
image(tmp2, main="pattern 2")
image(tmp3, main="pattern 3")

par(mar=c(4,4,0,1)) 
plot(T, tp1, t="l", xlab="", ylab="")
plot(T, tp2, t="l", xlab="", ylab="")
plot(T, tp3, t="l", xlab="", ylab="")

par(mar=c(4,4,3,1))
image(matrix(U[,1], length(x), length(y)), main="eof 1") 
image(matrix(U[,2], length(x), length(y)), main="eof 2")
image(matrix(U[,3], length(x), length(y)), main="eof 3")

par(mar=c(4,4,0,1)) 
plot(T, A[,1], t="l", xlab="", ylab="")
plot(T, A[,2], t="l", xlab="", ylab="")
plot(T, A[,3], t="l", xlab="", ylab="")

在此处输入图片说明

并且,这是我用来确定PC重要性的方法。基本上,经验法则是相邻的Lambda之间的差异必须大于其关联的误差。

###Determine significant EOFs

#North's Rule of Thumb
Lambda_err <- sqrt(2/dim(F)[2])*L
upper.lim <- L+Lambda_err
lower.lim <- L-Lambda_err
NORTHok=0*L
for(i in seq(L)){
    Lambdas <- L
    Lambdas[i] <- NaN
    nearest <- which.min(abs(L[i]-Lambdas))
    if(nearest > i){
        if(lower.lim[i] > upper.lim[nearest]) NORTHok[i] <- 1
    }
    if(nearest < i){
        if(upper.lim[i] < lower.lim[nearest]) NORTHok[i] <- 1
    }
}
n_sig <- min(which(NORTHok==0))-1

plot(L[1:10],log="y", ylab="Lambda (dots) and error (vertical lines)", xlab="EOF")
segments(x0=seq(L), y0=L-Lambda_err, x1=seq(L), y1=L+Lambda_err)
abline(v=n_sig+0.5, col=2, lty=2)
text(x=n_sig, y=mean(L[1:10]), labels="North's Rule of Thumb", srt=90, col=2)

在此处输入图片说明

我发现Björnsson和Venegas(1997)关于显着性检验的章节部分很有帮助-他们提到了三类检验,其中主要的方差类型可能是我希望使用的检验。指的是一种将时间维度改组并在许多排列上重新计算Lambda的蒙特卡洛方法。von Storch和Zweiers(1999)也提到了将Lambda光谱与参考“噪声”光谱进行比较的测试。在这两种情况下,我都不确定如何执行此操作,也不确定在给定排列确定的置信区间的情况下如何进行显着性检验。

谢谢你的帮助。

参考文献:Björnsson,H.和Venegas,SA(1997)。“气候数据的EOF和SVD分析手册”,麦吉尔大学,CCGCR报告第97-1号,魁北克省蒙特利尔,第52页。http://andvari.vedur.is/%7Efolk/halldor/PICKUP/eof.pdf

GR North,TL Bell,RF Cahalan和FJ Moeng。(1982)。经验正交函数估计中的抽样误差。星期一 威。修订版,110:699–706。

冯·斯托奇,H,兹维斯,固件(1999)。气候研究中的统计分析。剑桥大学出版社。


您对引导方法有什么参考?
迈克尔·

4
引导程序在这里不起作用。它不适用于几乎每个观察值都与几乎任何其他观察值相关联的数据集;它需要独立性或至少近似独立性(例如,时间序列中的混合条件)才能生成合理的数据副本。当然,有一些特殊的引导程序方案(例如,野生引导程序)可以规避这些问题。但是我对此不会打赌。而且,您确实需要阅读并阅读多元统计书籍,以免获得另一个无法辩驳的曲棍球棒作为答案。
StasK 2012年

2
@Marc在框中,您可能是指用于时间序列的各种块引导程序,MBB(移动块引导程序),CBB(循环块引导程序)或SBB(固定块引导程序),它们使用数据的时间块来估计模型参数。
Michael Chernick

3
@StasK我不知道您为什么认为您需要混合条件才能将引导应用于时间序列。基于模型的方法仅要求您拟合时间序列结构,然后就可以自举残差。因此,您可以将时间序列与趋势和季节性成分进行比较,并且仍然可以进行基于模型的引导。
迈克尔·切尔尼克

2
我没有全文,但您可以尝试看看:“ Hamid Babamoradi,Frans van den Berg,ÅsmundRinnan,基于Bootstrap的主成分分析置信度限制-案例研究,化学计量学和智能实验室系统,第1卷120,2013 1月15日,97-105页,ISSN 0169-7439,10.1016 / j.chemolab.2012.10.007(sciencedirect.com/science/article/pii/S0169743912002171)关键词:引导; PCA;置信限; BC < sub> a </ sub>;不确定性”
tomasz74

Answers:


19

尽管这是我的问题,但我将尝试在此处进行一些对话。自从我问这个问题以来已经有6个月了,很遗憾,没有给出完整的答案,我将尝试总结到目前为止所收集的信息,看看是否有人可以详细说明其余问题。请原谅冗长的答案,但我没有其他办法...

首先,我将演示使用可能更好的综合数据集的几种方法。它来自Beckers和Rixon(2003)的一篇论文,该论文说明了使用算法对空白数据进行EOF。如果有人感兴趣,我已经在R中复制了该算法(link)。

综合数据集:

#color palette
pal <- colorRampPalette(c("blue", "cyan", "yellow", "red"))

#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)
image(Xt, col=pal(100))

#Noise field
set.seed(1)
RAND <- matrix(runif(length(Xt), min=-1, max=1), nrow=nrow(Xt), ncol=ncol(Xt))
R <- RAND * N.S.ratio * Xt

#True field + Noise field
Xp <- Xt + R
image(Xp, col=pal(100))

在此处输入图片说明

因此,真实的数据字段Xt由9个信号组成,我在其中添加了一些噪声以创建观察到的字段Xp,该字段将在以下示例中使用。EOF的确定如下:

紧急行动

#make covariance matrix
C <- t(Xp) %*% Xp #cov(Xp)
image(C)

#Eigen decomposition
E <- svd(C)

#EOFs (U) and associated Lambda (L) 
U <- E$u
L <- E$d

#projection of data onto EOFs (U) to derive principle components (A)
A <- Xp %*% U

按照我在原始示例中使用的示例,我将通过North的经验法则来确定“重要的” EOF。

诺斯的经验法则

Lambda_err <- sqrt(2/dim(Xp)[2])*L
upper.lim <- L+Lambda_err
lower.lim <- L-Lambda_err
NORTHok=0*L
for(i in seq(L)){
    Lambdas <- L
    Lambdas[i] <- NaN
    nearest <- which.min(abs(L[i]-Lambdas))
    if(nearest > i){
        if(lower.lim[i] > upper.lim[nearest]) NORTHok[i] <- 1
    }
    if(nearest < i){
        if(upper.lim[i] < lower.lim[nearest]) NORTHok[i] <- 1
    }
}
n_sig <- min(which(NORTHok==0))-1
n_sig

plot(L[1:20],log="y", ylab="Lambda (dots) and error (vertical lines)", xlab="EOF")
segments(x0=seq(L), y0=L-Lambda_err, x1=seq(L), y1=L+Lambda_err)
abline(v=n_sig+0.5, col=2, lty=2)
text(x=n_sig, y=mean(L[1:10]), labels="North's Rule of Thumb", srt=90, col=2)

在此处输入图片说明

由于2:4的Lambda值在幅度上非常接近,因此根据经验法则,这些值无关紧要-即,如果它们的幅度相似,它们各自的EOF模式可能会重叠并混合。鉴于我们知道该字段中实际存在9个信号,因此这很不幸。

一种更主观的方法是查看对数转换后的Lambda值(“ Scree图”),然后将回归拟合到尾随值。然后,可以从视觉上确定此行上方的lambda值处于什么级别:

碎石图

ntrail <- 35
tail(L, ntrail)
fit <- lm(log(tail(L, ntrail)) ~ seq(length(L)-ntrail+1, length(L)))
plot(log(L))
abline(fit, col=2)

在此处输入图片说明

因此,这5条领先的EOF位于这条线之上。当Xp没有添加额外的噪声并且结果显示所有9个原始信号时,我都尝试了此示例。因此,EOF 6:9的微不足道是因为它们的幅度低于现场的噪声。

更为客观的方法是Overland和Preisendorfer(1982)提出的“规则N”标准。包中有一个实现wq,下面显示。

规则N

library(wq)
eofNum(Xp, distr = "normal", reps = 99)

RN <- ruleN(nrow(Xp), ncol(Xp), type = "normal", reps = 99)
RN
eigs <- svd(cov(Xp))$d
plot(eigs, log="y")
lines(RN, col=2, lty=2)

在此处输入图片说明

规则N确定了4个重要的EOF。我个人需要更好地了解这种方法。为什么可以根据不使用与in中相同分布的随机字段来评估错误级别Xp?此方法的一种变体是对数据进行重新采样,以Xp使每一列随机重新排列。这样,我们确保随机字段的总方差与相同Xp。通过多次采样,我们便能够计算出分解的基线误差。

蒙特卡洛与随机场(即空模型比较)

iter <- 499
LAMBDA <- matrix(NaN, ncol=iter, nrow=dim(Xp)[2])

set.seed(1)
for(i in seq(iter)){
    #i=1

    #random reorganize dimensions of scaled field
    Xp.tmp <- NaN*Xp
    for(j in seq(dim(Xp.tmp)[2])){
        #j=1
        Xp.tmp[,j] <- Xp[,j][sample(nrow(Xp))]
    }

    #make covariance matrix
    C.tmp <- t(Xp.tmp) %*% Xp.tmp #cov(Xp.tmp)

    #SVD decomposition
    E.tmp <- svd(C.tmp)

    #record Lambda (L) 
    LAMBDA[,i] <- E.tmp$d

    print(paste(round(i/iter*100), "%", " completed", sep=""))
}

boxplot(t(LAMBDA), log="y", col=8, border=2, outpch="")
points(L)

在此处输入图片说明

同样,在随机字段的分布上方有4个EOF。我对此方法以及规则N感到担心的是,这些方法并没有真正解决Lambda值的置信区间;例如,较高的第一Lambda值将自动导致较低的方差量(由尾随的方差解释)。因此,根据随机场计算出的Lambda斜率始终较小,并可能导致选择的有效EOF太少。[注意:该eofNum()函数假定EOF是根据相关矩阵计算得出的。如果使用例如协方差矩阵(居中但未缩放的数据),则此数字可能会有所不同。]

最后,@ tomasz74提到了Babamoradi等人的论文。(2013),我对此进行了简要介绍。它非常有趣,但似乎更侧重于计算EOF载荷和系数的CI,而不是Lambda。尽管如此,我相信可以采用相同的方法来评估Lambda错误。通过对行进行重新采样,直到产生一个新字段,对数据字段进行引导重新采样。同一行可以多次采样,这是一种非参数方法,不需要对数据的分布进行假设。

Lambda值的引导程序

B <- 40 * nrow(Xp)
LAMBDA <- matrix(NaN, nrow=length(L), ncol=B)
for(b in seq(B)){
    samp.b <- NaN*seq(nrow(Xp))
    for(i in seq(nrow(Xp))){
        samp.b[i] <- sample(nrow(Xp), 1)
    }
    Xp.b  <- Xp[samp.b,]
    C.b  <- t(Xp.b) %*% Xp.b 
    E.b  <- svd(C.b)
    LAMBDA[,b] <- E.b$d
    print(paste(round(b/B*100), "%", " completed", sep=""))
}
boxplot(t(LAMBDA), log="y", col=8, outpch="", ylab="Lambda [log-scale]")
points(L, col=4)
legend("topright", legend=c("Original"), pch=1, col=4)

在此处输入图片说明

尽管这对于计算Lambda值的误差可能比North的经验法则更为稳健,但我现在认为,EOF重要性的问题归结于对这意味着什么的不同观点。对于North的经验法则和自举法,重要性似乎更多地取决于teere是否在Lambda值之间重叠。如果存在,则这些EOF可能会混入其信号中,而不代表“真实”模式。另一方面,这两个EOF可能描述了大量的方差(与随机字段的分解(例如规则N)相比)。因此,如果有兴趣滤除噪声(即通过EOF截断),则规则N就足够了。如果有兴趣确定数据集中的真实模式,则更严格的Lambda重叠标准可能会更可靠。

同样,我不是这些问题的专家,所以我仍然希望有更多经验的人可以对此进行补充。

参考文献:

Beckers,Jean-Marie和M.Rixen。“ EOF计算和来自不完整海洋学数据集的数据填充。” 大气与海洋技术学报20.12(2003):1839-1856。

J.Overland和R.Preisendorfer,《应用于旋风气候学的主要成分的显着性检验》,星期一。威。修订版,110,1-4,1982。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.