Як визначити важливі основні компоненти, використовуючи завантажувальний інструмент або підхід Монте-Карло?


40

Мені цікаво визначити кількість значущих закономірностей, що виходять з аналізу основних компонентів (PCA) або аналізу емпіричної ортогональної функції (EOF). Мені особливо цікаво застосувати цей метод до даних про клімат. Поле даних є матрицею MxN, причому M є часовим розміром (наприклад, днями), а N - просторовим розміром (наприклад, місця розташування / відстань). Я читав про можливий метод завантаження для визначення значущих ПК, але не зміг знайти більш детальний опис. До цих пір я застосовував Норт-норму Палата (North et al ., 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="")

введіть тут опис зображення

І ось метод, який я використовую для визначення значущості для ПК. В основному, правило полягає в тому, що різниця між сусідніми лямбдами повинна бути більшою, ніж пов'язана з ними помилка.

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

введіть тут опис зображення

Я вважаю, що розділ глави Бьорнссона та Венегасу ( 1997 ) про тести на значущість є корисним - вони посилаються на три категорії тестів, серед яких домінуючий тип дисперсії - це, мабуть, те, що я сподіваюся використовувати. Посилання на тип підходу в Монте-Карло щодо переміщення часового виміру та перерахування Лямбда за багато перестановок. фон Сторч і Цвейер (1999) також посилаються на тест, який порівнює спектр Ламбда з еталонним "шумовим" спектром. В обох випадках я трохи не впевнений у тому, як це можна зробити, а також, як проводиться тест на значимість, враховуючи інтервали довіри, визначені перестановками.

Спасибі за вашу допомогу.

Список літератури: Björnsson, H. and Venegas, SA (1997). "Посібник для аналізів кліматичних даних EOF та SVD", Університет Макгілл, Доповідь CCGCR № 97-1, Montréal, Québec, 52pp. http://andvari.vedur.is/%7Efolk/halldor/PICKUP/eof.pdf

GR North, TL Bell, RF Cahalan і FJ Moeng. (1982). Помилки вибірки в оцінці емпіричних ортогональних функцій. Пн. Wea. Откр., 110: 699–706.

фон Сторч, H, Zwiers, FW (1999). Статистичний аналіз в кліматичних дослідженнях. Cambridge University Press.


Яка ваша посилання на підхід до завантаження?
Майкл Черник

4
Тут не працюватиме завантажувальна стрічка. Він не буде працювати з наборами даних, в яких майже кожне спостереження співвідноситься з майже будь-яким іншим спостереженням; їй потрібна незалежність або хоча б приблизна незалежність (умови змішування у часових рядах, скажімо), щоб отримати виправдані копії даних. Звичайно, існують спеціальні схеми завантаження, наприклад, дикі завантажувачі, які можуть обійти ці проблеми. Але я на це не буду багато робити ставку. І вам справді потрібно переглянути багатоваріантні статистичні книги та стежити за ними, щоб не отримати ще одну невідправну хокейну паличку як відповідь.
Стаск

2
@Marc у полі Ви можете посилатися на різні блокові завантажувальні пристрої, які використовуються для часових рядів, MBB (рухомий блок завантажувального блоку), CBB (круговий блок завантаження), або SBB (стаціонарна блокова завантажувальна машина), які використовують часові блоки даних для оцінки моделі параметри.
Майкл Черник

3
@StasK Я не знаю, чому ви вважаєте, що вам потрібні умови змішування для застосування завантажувальної програми до часових рядів. Методи на основі моделей просто вимагають, щоб ви підходили до структури часових рядів, і тоді ви можете завантажувати залишки. Таким чином, ви можете мати часові ряди з тенденціями та сезонними компонентами та все ж робити завантажувальну модель на основі моделей.
Майкл Черник

2
У мене немає доступу до повного тексту, але ви можете спробувати поглянути: "Хамід Бабамораді, Франс ван ден Берг, Есмунд Ріннан, Bootstrap визначають обмеження довіри в аналізі основних компонентів - Тематичне дослідження, хіміометрія та інтелектуальні лабораторні системи, том" 120, 15 січня 2013, сторінки 97-105, ISSN 0169-7439, 10.1016 / j.chemolab.2012.10.007 (. sciencedirect.com/science/article/pii/S0169743912002171 ) Ключові слова: Bootstrap, PCA, Довірчі, BC < sub> a </sub>; Невизначеність "
tomasz74

Відповіді:


19

Я спробую трохи просунути діалог тут, хоча це моє питання. Пройшло 6 місяців, як я запитав це, і, на жаль, не було отримано повних відповідей, я спробую підсумувати те, що я зібрав до цього часу, і побачу, чи хтось може детальніше розглянути інші питання. Вибачте, будь ласка, довгу відповідь, але я не бачу іншого шляху ...

По-перше, я продемонструю кілька підходів, використовуючи можливо кращий синтетичний набір даних. Він походить з доповіді Беккерса та Ріксона ( 2003 ), що ілюструє використання алгоритму для проведення EOF за неодноразовими даними. Я відтворив алгоритм в R, якщо хтось зацікавлений ( посилання ).

Синтетичний набір даних:

#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 визначаються як такі:

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

Слідуючи прикладу, який я використав у своєму оригінальному прикладі, я визначу "значні" коефіцієнти коефіцієнта корисної дії за допомогою правильного правила Норта.

Нормове правило великого пальця

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 дуже близькі між собою за амплітудою, вони вважаються незначними за правилом, тобто їх відповідні шаблони EOF можуть перетинатись та змішуватися з огляду на їх схожі амплітуди. Це прикро, враховуючи, що ми знаємо, що в полі насправді існує 9 сигналів.

Більш суб'єктивний підхід полягає в перегляді значень лямбда, трансформованих журналом ("Екран екрану"), а потім пристосування регресії до кінцевих значень. Потім можна візуально визначити, на якому рівні значення лямбда лежать над цією лінією:

Скріп сюжету

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 провідних ЕФО лежать над цією лінією. Я спробував цей приклад, коли Xpне додано додаткових шумів і результати виявляють усі 9 оригінальних сигналів. Отже, незначність EOF 6: 9 пояснюється тим, що їх амплітуда менша, ніж шум у полі.

Більш об'єктивним методом є критерії "Правила N" Overland і Preisendorfer (1982). В рамках 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. Особисто мені потрібно краще зрозуміти цей метод; Чому можна оцінити рівень помилки на основі випадкового поля, яке не використовує те саме розподіл, що і в 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, полягає в тому, що вони справді не стосуються довірчих інтервалів значень Ламбда; наприклад, високе перше значення лямбда автоматично призведе до меншої кількості дисперсії, що пояснюється прорахунковими. Таким чином, лямбда, обчислена з випадкових полів, завжди матиме менш крутий нахил і може призвести до вибору занадто мало значущих коефіцієнтів коефіцієнта корисної дії. [ПРИМІТКА: Ця eofNum()функція передбачає, що коефіцієнти коефіцієнта корисних копалин обчислюються з кореляційної матриці. Це число може бути різним, якщо використовується, наприклад, матриця коваріації (по центру, але не масштабується).]

Нарешті, @ tomasz74 згадав статтю Бабамораді та ін. (2013), який я коротко ознайомився. Це дуже цікаво, але, здається, більш орієнтоване на обчислення КІ навантажень та коефіцієнтів EOF, а не на 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)

введіть тут опис зображення

Хоча це може бути більш надійним, ніж правило Норта для обчислення похибки значень Лямбда, я вважаю, що питання про значення EOF зводиться до різних думок щодо того, що це означає. Для методу правила Півночі з великим пальцем та завантажувальним принципом, схоже, важливість більшою мірою базується на тому, чи збігається перекриття між значеннями лямбда. Якщо є, то ці EOF можуть бути змішані у своїх сигналах і не представляти "справжніх" зразків. З іншого боку, ці два КВ можуть описувати значну кількість дисперсії (порівняно з розкладанням випадкового поля - наприклад, Правилом N). Отже, якщо хтось зацікавлений у відфільтруванні шуму (тобто через усічення EOF), то правила N буде достатньо. Якщо хтось зацікавлений у визначенні реальних шаблонів у наборі даних, то більш жорсткі критерії ламбда-перекриття можуть бути більш надійними.

Знову ж таки, я не є експертом у цих питаннях, тому все ще сподіваюся, що хтось із більшим досвідом може додати до цього пояснення.

Список літератури:

Беккерс, Жан-Марі та М. Ріксен. "Розрахунки EOF та заповнення даних з неповних наборів океанографічних даних." Журнал атмосферних та океанічних технологій 20.12 (2003): 1839-1856.

Overland, J. та R. Preisendorfer, Тест на значущість основних компонентів, застосованих до циклонової кліматології, Пн. Wea. Вип., 110, 1–4, 1982.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.