Wie werden wichtige Hauptkomponenten mithilfe des Bootstrapping- oder Monte-Carlo-Ansatzes ermittelt?

40

Ich bin daran interessiert, die Anzahl signifikanter Muster zu bestimmen, die aus einer Hauptkomponentenanalyse (PCA) oder einer empirischen Orthogonalfunktionsanalyse (EOF) hervorgehen. Ich bin besonders daran interessiert, diese Methode auf Klimadaten anzuwenden. Das Datenfeld ist eine MxN-Matrix, wobei M die Zeitdimension (z. B. Tage) und N die räumliche Dimension (z. B. Lon / Lat-Standorte) ist. Ich habe von einer möglichen Bootstrap-Methode gelesen, um wichtige PCs zu bestimmen, konnte jedoch keine detailliertere Beschreibung finden. Bisher habe ich die Faustregel von North (North et al ., 1982) angewendet, um diesen Grenzwert zu bestimmen, aber ich habe mich gefragt, ob eine robustere Methode verfügbar ist.

Als Beispiel:

###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="")

Bildbeschreibung hier eingeben

Und hier ist die Methode, mit der ich die Bedeutung des PCs ermittelt habe. Grundsätzlich gilt als Faustregel, dass der Unterschied zwischen benachbarten Lambdas größer sein muss als der zugehörige Fehler.

###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)

Bildbeschreibung hier eingeben

Ich habe den Kapitelabschnitt von Björnsson und Venegas ( 1997 ) über Signifikanztests als hilfreich empfunden - sie beziehen sich auf drei Kategorien von Tests, von denen der dominante Varianztyp wahrscheinlich das ist, was ich zu verwenden hoffe. Sie beziehen sich auf eine Art Monte-Carlo-Ansatz, bei dem die Zeitdimension gemischt und die Lambdas über viele Permutationen neu berechnet werden. von Storch und Zweiers (1999) verweisen auch auf einen Test, der das Lambda-Spektrum mit einem Referenz- "Rausch" -Spektrum vergleicht. In beiden Fällen bin ich mir etwas unsicher, wie dies getan werden könnte und wie der Signifikanztest angesichts der durch die Permutationen identifizierten Konfidenzintervalle durchgeführt wird.

Danke für Ihre Hilfe.

Referenzen: Björnsson, H. und Venegas, SA (1997). "Ein Handbuch für EOF- und SVD-Analysen von Klimadaten", McGill University, CCGCR-Bericht Nr. 97-1, Montréal, Québec, 52 Seiten. http://andvari.vedur.is/%7Efolk/halldor/PICKUP/eof.pdf

GR Nord, TL Bell, RF Cahalan und FJ Moeng. (1982). Abtastfehler bei der Schätzung empirischer orthogonaler Funktionen. Montag Wea. Rev. 110: 699–706.

von Storch, H., Zwiers, FW (1999). Statistische Analyse in der Klimaforschung. Cambridge University Press.

Marc in der Kiste
quelle
Was ist Ihre Referenz zum Bootstrap-Ansatz?
Michael Chernick
4
Ein Bootstrap wird hier nicht funktionieren. Es funktioniert nicht mit den Datensätzen, in denen so gut wie jede Beobachtung mit so gut wie jeder anderen Beobachtung korreliert. Es braucht Unabhängigkeit oder zumindest eine ungefähre Unabhängigkeit (etwa Mischungsbedingungen in Zeitreihen), um gerechtfertigte Replikate der Daten zu erstellen. Natürlich gibt es spezielle Bootstrap-Schemata wie den Wild Bootstrap, die diese Probleme umgehen können. Aber ich werde nicht viel darauf setzen. Und Sie müssen sich wirklich multivariate Statistikbücher ansehen und ihnen folgen, um nicht noch einen weiteren nicht zu rechtfertigenden Hockeyschläger als Antwort zu erhalten.
StasK
2
@Marc in der Box bezieht sich möglicherweise auf verschiedene Block-Bootstraps, die für Zeitreihen verwendet werden, MBB (Moving Block Bootstrap), CBB (Circular Block Bootstrap) oder SBB (Stationary Block Bootstrap), die Zeitblöcke der Daten zum Schätzen des Modells verwenden Parameter.
Michael Chernick
3
@StasK Ich weiß nicht, warum Sie der Meinung sind, dass Sie Mischbedingungen benötigen, um Bootstrap auf Zeitreihen anzuwenden. Bei modellbasierten Methoden müssen Sie lediglich eine Zeitreihenstruktur anpassen und können dann Residuen booten. Sie könnten also Zeitreihen mit Trends und saisonalen Komponenten haben und trotzdem modellbasiertes Bootstrap durchführen.
Michael Chernick
2
Ich habe keinen Zugang zum Volltext, aber Sie können versuchen, einen Blick darauf zu werfen: "Hamid Babamoradi, Frans van den Berg, Åsmund Rinnan, Bootstrap-basierte Vertrauensgrenzen in der Hauptkomponentenanalyse - Eine Fallstudie, Chemometrics and Intelligent Laboratory Systems, Volume 120, 15. Januar 2013, Seiten 97-105, ISSN 0169-7439, 10.1016 / j.chemolab.2012.10.007. ( Sciencedirect.com/science/article/pii/S0169743912002171 ) Keywords: Bootstrap; PCA; Confidence limits; BC < sub> a </ sub>; Unsicherheit "
tomasz74

Antworten:

19

Ich werde versuchen, den Dialog hier ein wenig voranzutreiben, obwohl dies meine Frage ist. Es ist 6 Monate her, seit ich dies gefragt habe, und leider wurden keine vollständigen Antworten gegeben. Ich werde versuchen, das, was ich bisher gesammelt habe, zusammenzufassen und zu prüfen, ob jemand auf die verbleibenden Probleme eingehen kann. Bitte entschuldigen Sie die lange Antwort, aber ich sehe keinen anderen Weg ...

Zunächst werde ich verschiedene Ansätze anhand eines möglicherweise besseren synthetischen Datensatzes demonstrieren. Es stammt aus einem Aufsatz von Beckers und Rixon ( 2003 ), der die Verwendung eines Algorithmus zur Durchführung von EOF auf Gappy-Daten veranschaulicht. Ich habe den Algorithmus in R reproduziert, wenn jemand interessiert ist ( Link ).

Synthetischer Datensatz:

#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))

Bildbeschreibung hier eingeben

Also das wahre Datenfeld Xt besteht also aus 9 Signalen, und ich habe etwas Rauschen hinzugefügt, um das beobachtete Feld zu erzeugen Xp, das in den folgenden Beispielen verwendet wird. Die EOFs werden als solche bestimmt:

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

Nach dem Beispiel, das ich in meinem ursprünglichen Beispiel verwendet habe, werde ich "signifikante" EOFs anhand der Faustregel von North ermitteln.

Nords Faustregel

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)

Bildbeschreibung hier eingeben

Da die Lambda-Werte von 2: 4 in der Amplitude sehr nahe beieinander liegen, werden diese von der Faustregel als unbedeutend angesehen, dh ihre jeweiligen EOF-Muster könnten sich bei ähnlichen Amplituden überlappen und mischen. Dies ist bedauerlich, da wir wissen, dass tatsächlich 9 Signale im Feld vorhanden sind.

Ein subjektiverer Ansatz besteht darin, die logarithmisch transformierten Lambda-Werte ("Scree-Plot") anzuzeigen und dann eine Regression an die nachfolgenden Werte anzupassen. Man kann dann visuell feststellen, auf welcher Höhe die Lambdawerte oberhalb dieser Linie liegen:

Geröll Grundstück

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)

Bildbeschreibung hier eingeben

Die 5 führenden EOFs liegen also oberhalb dieser Linie. Ich habe dieses Beispiel ausprobiert, bei dem Xpkein zusätzliches Rauschen hinzugefügt wurde und die Ergebnisse alle 9 Originalsignale enthüllen. Die Bedeutungslosigkeit der EOFs 6: 9 beruht auf der Tatsache, dass ihre Amplitude geringer ist als das Rauschen im Feld.

Eine objektivere Methode sind die "Regel N" -Kriterien von Overland und Preisendorfer (1982). Es gibt eine Implementierung innerhalb des wqPakets, die ich unten zeige.

Regel 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)

Bildbeschreibung hier eingeben

Die Regel N identifizierte 4 signifikante EOFs. Persönlich muss ich diese Methode besser verstehen; Warum ist es möglich, die Fehlerquote anhand eines zufälligen Feldes zu bestimmen, das nicht die gleiche Verteilung verwendet wie das in Xp? Eine Variation dieser Methode besteht darin, die Daten neu abzutasten, Xpsodass jede Spalte nach dem Zufallsprinzip neu gemischt wird. Auf diese Weise stellen wir sicher, dass die Gesamtvarianz des Zufallsfeldes gleich ist wie Xp. Durch mehrmaliges Resampling können wir dann einen Grundlinienfehler der Zerlegung berechnen.

Monte Carlo mit Zufallsfeld (dh Nullmodellvergleich)

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)

Bildbeschreibung hier eingeben

Wiederum liegen 4 EOFs über den Verteilungen für die Zufallsfelder. Ich mache mir Sorgen mit diesem Ansatz und dem von Regel N, dass diese die Vertrauensbereiche der Lambda-Werte nicht wirklich berücksichtigen. Zum Beispiel führt ein hoher erster Lambda-Wert automatisch zu einer geringeren Varianz, die durch nachfolgende zu erklären ist. Das aus Zufallsfeldern berechnete Lambda weist daher immer eine geringere Steilheit auf und kann dazu führen, dass zu wenige signifikante EOFs ausgewählt werden. [Beachten Sie daseofNum() Funktion geht davon aus, dass EOFs aus einer Korrelationsmatrix berechnet werden. Diese Zahl kann abweichen, wenn Sie z. B. eine Kovarianzmatrix verwenden (zentrierte, aber nicht skalierte Daten).]

Schließlich erwähnte @ tomasz74 das Papier von Babamoradi et al. (2013), die ich mir kurz angeschaut habe. Es ist sehr interessant, scheint sich aber eher auf die Berechnung von CIs von EOF-Belastungen und -Koeffizienten als auf Lambda zu konzentrieren. Dennoch glaube ich, dass es übernommen werden könnte, Lambda-Fehler nach derselben Methodik zu bewerten. Ein Bootstrap-Resampling des Datenfelds wird durchgeführt, indem die Zeilen erneut abgetastet werden, bis ein neues Feld erzeugt wird. Dieselbe Zeile kann mehrmals neu abgetastet werden. Dies ist ein nicht parametrischer Ansatz, und es müssen keine Annahmen über die Verteilung der Daten getroffen werden.

Bootstrap von Lambda-Werten

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)

Bildbeschreibung hier eingeben

Dies mag zwar robuster sein als die Faustregel von North zur Berechnung des Fehlers der Lambda-Werte, aber ich glaube jetzt, dass die Frage der EOF-Signifikanz auf unterschiedliche Meinungen darüber hinausläuft, was dies bedeutet. Für die Faustregel des Nordens und die Bootstrap-Methoden scheint die Signifikanz eher darauf zu beruhen, ob sich die Lambda-Werte überlappen oder nicht. Wenn dies der Fall ist, können diese EOFs in ihre Signale gemischt werden und stellen keine "wahren" Muster dar. Andererseits können diese beiden EOFs ein signifikantes Maß an Varianz beschreiben (im Vergleich zur Zerlegung eines Zufallsfeldes - z. B. Regel N). Wenn man also daran interessiert ist, Rauschen (dh über EOF-Trunkierung) herauszufiltern, wäre Regel N ausreichend. Wenn man reelle Muster in einem Datensatz bestimmen möchte, sind die strengeren Kriterien der Lambda-Überlappung möglicherweise robuster.

Auch hier bin ich kein Experte in diesen Fragen. Ich hoffe immer noch, dass jemand mit mehr Erfahrung diese Erklärung ergänzen kann.

Verweise:

Beckers, Jean-Marie und M. Rixen. "EOF-Berechnungen und Datenfüllung aus unvollständigen ozeanografischen Datensätzen." Journal of Atmospheric and Oceanic Technology 20.12 (2003): 1839-1856.

Overland, J., und R. Preisendorfer, Ein Signifikanztest für Hauptkomponenten, die auf eine Zyklonklimatologie angewendet werden. Wea. Rev., 110, 1-4, 1982.

Marc in der Kiste
quelle