Saya mendapatkan pemuatan "gelisah" di rollapply PCA di R. Dapatkah saya memperbaikinya?


20

Saya memiliki data pengembalian harian 10 tahun untuk 28 mata uang yang berbeda. Saya ingin mengekstraksi komponen utama pertama, tetapi alih-alih mengoperasikan PCA selama 10 tahun penuh, saya ingin membuka jendela 2 tahun, karena perilaku mata uang berkembang dan saya ingin merefleksikan ini. Namun saya memiliki masalah besar, yaitu bahwa kedua fungsi princomp () dan prcomp () akan sering melompat dari muatan positif ke negatif dalam analisis PCA yang berdekatan (yaitu terpisah 1 hari). Lihatlah grafik pemuatan untuk mata uang EUR:

masukkan deskripsi gambar di sini

Jelas saya tidak bisa menggunakan ini karena pemuatan yang berdekatan akan melompat dari positif ke negatif, jadi seri saya yang menggunakannya akan salah. Sekarang lihat nilai absolut dari pemuatan mata uang EUR:

masukkan deskripsi gambar di sini

Masalahnya tentu saja saya masih tidak dapat menggunakan ini karena Anda dapat melihat dari grafik atas bahwa pemuatan tidak berubah dari negatif ke positif dan kembali pada waktu, suatu karakteristik yang saya perlu pertahankan.

Apakah ada cara saya bisa mengatasi masalah ini? Bisakah saya memaksakan orientasi vektor eigen untuk selalu sama di PCA yang berdekatan?

By the way masalah ini juga terjadi dengan fungsi FactoMineR PCA (). Kode untuk rollapply ada di sini:

rollapply(retmat, windowl, function(x) summary(princomp(x))$loadings[, 1], by.column = FALSE, align = "right") -> princomproll

3
Bisakah Anda menjelaskan apa yang Anda maksud dengan "orientasi" vektor eigen? Sejauh yang saya tahu, tidak ada hal yang intrinsik dengan data. (Itulah salah satu alasan mengapa perangkat lunak yang berbeda akan menghasilkan vektor eigen yang dinormalisasi berbeda.) Jadi sepertinya Anda meminta sesuatu yang tidak ada dan tidak ada artinya.
whuber

1
Nah pada suatu hari saya akan mendapatkan pemuatan seperti ini: EUR -0.2 ZAR +0.8 USD +0.41 ..... 28 mata uang. Dan hari berikutnya saya akan mendapatkan EUR +0,21 ZAR -0,79 USD -0,4 dll. Jadi poros yang PCA telah pilih untuk memutar data ke berorientasi persis sebaliknya pada hari 2, dibandingkan dengan hari 1. Itu menyebabkan pemuatan ini melompat dan saya ingin menghindarinya, entah bagaimana ...... Maaf jika terminologi saya menyesatkan. Saya mengerti bahwa kode PCA tidak benar-benar peduli tentang orientasi sumbu selama konsisten di memuat pada satu hari , tetapi saya harus konsisten di beberapa hari.
Thomas Browne

1
dengan mengingat bahwa dari satu hari ke hari berikutnya, mengingat jendela 2 tahun bergulir pada data harian, kita harus memiliki PCA yang sangat, sangat mirip.
Thomas Browne

Saya pikir alasan Anda memiliki masalah adalah bahwa ide yang tidak masuk akal ini tidak masuk akal. Saya tidak punya solusi selain mencari sesuatu yang berbeda yang dapat mencapai tujuan Anda (tidak yakin apa tujuan mereka) dan masuk akal.
Michael R. Chernick

EUR -0.2 ZAR +0.8 USD +0.41dan EUR +0.21 ZAR -0.79 USD -0.4 yang sangat sangat mirip. Anda cukup membalikkan masuk salah satu dari dua hasil.
ttnphns

Jawaban:


22

Setiap kali plot melompat terlalu banyak, balikkan orientasinya. Salah satu kriteria yang efektif adalah ini: hitung jumlah total lompatan pada semua komponen. Hitung jumlah total lompatan jika vektor eigen berikutnya dinegasikan. Jika yang terakhir kurang, meniadakan vektor eigen berikutnya.

Inilah implementasi. (Saya tidak terbiasa dengan zoo, yang mungkin memungkinkan solusi yang lebih elegan.)

require(zoo)
amend <- function(result) {
  result.m <- as.matrix(result)
  n <- dim(result.m)[1]
  delta <- apply(abs(result.m[-1,] - result.m[-n,]), 1, sum)
  delta.1 <- apply(abs(result.m[-1,] + result.m[-n,]), 1, sum)
  signs <- c(1, cumprod(rep(-1, n-1) ^ (delta.1 <= delta)))
  zoo(result * signs)
}

Sebagai contoh, mari kita jalankan jalan acak dalam kelompok ortogonal dan sedikit gugup untuk kepentingan:

random.rotation <- function(eps) {
  theta <- rnorm(3, sd=eps)
  matrix(c(1, theta[1:2], -theta[1], 1, theta[3], -theta[2:3], 1), 3)
}
set.seed(17)
n.times <- 1000
x <- matrix(1., nrow=n.times, ncol=3)
for (i in 2:n.times) {
  x[i,] <- random.rotation(.05) %*% x[i-1,]
}

Inilah PCA bergulir:

window <- 31
data <- zoo(x)
result <- rollapply(data, window, 
  function(x) summary(princomp(x))$loadings[, 1], by.column = FALSE, align = "right")
plot(result)

Asli

Sekarang versi tetap:

plot(amend(result))

Diubah


Saya membatalkan jawaban yang bagus ini sejak lama, tetapi sekarang kembali ke sana karena saya harus mengimplementasikan sesuatu yang serupa. Pendekatan yang saya pilih (sebelum mencari di posting Anda lagi) adalah untuk pergi melalui semua titik waktu dan menghitung titik produk antara vektor eigen terkemuka (sumbu PC pertama) pada timestep dan vektor eigen pada langkah sebelumnya . Jika produk titik ini mendekati , jangan lakukan apa pun. Itu mendekati , balikkan arah . Algoritme Anda tampaknya sedikit berbeda. Apakah akan bekerja dengan cara yang sama? v i + 1 i + 1 v i i 1 - 1 v i + 1tivi+1i+1vii11vi+1
amoeba mengatakan Reinstate Monica

@amoeba Meskipun saya tidak yakin persis apa yang Anda lakukan, sepertinya beberapa ide yang dibahas dalam jawaban David J. Harris dan komentar yang mengikutinya. Lihat, khususnya, komentar saya di stats.stackexchange.com/questions/34396/… .
Whuber

2
@ Art, jadi seperti yang saya mengerti, Anda ingin memperbaiki tanda komponen berdasarkan pada beberapa preferensi eksternal (eksternal ke PCA). Ini baik-baik saja, tetapi itu adalah bagaimana Anda harus mendekatinya. Pertama lakukan hal geser PCA, memastikan bahwa tanda-tanda konsisten. Dan kemudian memutuskan, berdasarkan beberapa kriteria tambahan, apakah akan membalik seluruh komponen atau tidak. Misalnya Anda dapat menghubungkannya dengan tren euro dan jika korelasinya negatif, balikkan komponennya. Atau semacam itu. Ini sepenuhnya tergantung pada aplikasi spesifik Anda dan pada pengetahuan domain Anda.
Amuba mengatakan Reinstate Monica

1
Saya setuju dengan interpretasi dan rekomendasi @ amoeba.
whuber

1
@amoeba: ya, Anda benar tentang ini, walaupun, saya naif berpikir bahwa mungkin ada beberapa solusi generik yang tidak tergantung pada seri waktu tertentu, sesuatu seperti "orientasi nyata dari vektor" :) tetap, terima kasih atas bantuan dan saran
Anonim

8

@whuber benar bahwa tidak ada orientasi yang intrinsik dengan data, tetapi Anda masih bisa memastikan bahwa vektor eigen Anda memiliki korelasi positif dengan beberapa vektor referensi.

Misalnya, Anda dapat membuat pemuatan untuk USD positif pada semua vektor eigen Anda (yaitu, jika pemuatan USD negatif, balikkan tanda-tanda seluruh vektor). Arah keseluruhan vektor Anda masih sewenang-wenang (karena Anda bisa menggunakan EUR atau ZAR sebagai referensi Anda sebagai gantinya), tetapi beberapa sumbu pertama PCA Anda mungkin tidak akan melonjak hampir sebanyak - terutama karena jendela bergulir Anda sangat panjang.


7
Ide bagus. Saya mencoba ini dulu (mungkin saat Anda memposting jawaban ini :-). Masalahnya adalah bahwa muatan lainnya dapat melompat-lompat. Untuk mengatasinya, dasarkan pilihan tanda pada pemuatan terbesar. Masih tidak ada dadu: pemuatan masih bisa melompat. Caranya adalah pada setiap waktu untuk memilih orientasi yang menciptakan gangguan paling sedikit dalam vektor pemuatan dari waktu sebelumnya.
whuber

4
@whuber Kerja bagus.
David J. Harris

1
Benar, tanda memuat tidak masalah (orientasi). Sesuatu yang tidak ditangani adalah bahwa jika Anda melakukan ini di berbagai paket perangkat lunak, perbedaan antara paket adalah bahwa satu program dapat menghasilkan tanda-tanda negatif (positif) pada pemuatan tertentu sementara yang lain menghasilkan tanda-tanda positif (negatif) untuk pemuatan yang sama. Oleh karena itu, tanda-tanda hasil akhir dalam plot 3-seri di atas dapat dibalik ketika menggunakan paket lain. Referensi memuat vektor juga bisa memiliki perubahan tanda - dan solusi ini tidak akan salah.
JoleT

@LEP: Saya menghadapi masalah yang sama dengan inversi, mungkin Anda sudah menemukan solusi untuk masalah ini - bagaimana cara mengetahui bahwa vektor pertama sudah benar dan memastikan bahwa sisanya akan diselaraskan dengan benar - quant.stackexchange.com/questions / 3094 / ... ?
Anonim

Selama matriks tidak tunggal dan tidak ada nilai eigennya nol, sebagian besar hasil algoritma harus sama, kecuali untuk perubahan 180 derajat pada tanda-tanda - yang tidak dijamin.
JoleT

1

Apa yang saya lakukan adalah menghitung jarak L1 antara vektor eigen berturut-turut. Setelah menormalkan matriks ini, saya memilih ambang skor az misalnya 1, sehingga jika dalam setiap pengguliran baru perubahannya di atas ambang ini, saya membalik vektor eigen, faktor, dan pemuatan agar memiliki konsistensi di jendela penguliran. Secara pribadi saya tidak suka memaksa tanda-tanda yang diberikan dalam beberapa korelasi karena mereka bisa sangat tidak stabil tergantung dari driver makro.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.