Kekhawatiran pertanyaan bagaimana untuk menghasilkan variates acak dari distribusi normal multivariat dengan (mungkin) singular kovarians matriks C . Jawaban ini menjelaskan satu cara yang akan bekerja untuk matriks kovarian apa pun . Ini menyediakan R
implementasi yang menguji akurasinya.
Analisis aljabar dari matriks kovarians
Karena C adalah matriks kovarians, ia harus simetris dan positif-semidefinit. Untuk melengkapi informasi latar belakang, biarkan μ menjadi vektor dari cara yang diinginkan.
Karena simetris, Dekomposisi Nilai Singular (SVD) dan dekomposisi eigendnya akan secara otomatis berbentukC
C=VD2V′
untuk beberapa ortogonal matriks dan matriks diagonal D 2 . Secara umum elemen diagonal D 2 adalah nonnegatif (menyiratkan mereka semua memiliki akar kuadrat nyata: pilih yang positif untuk membentuk matriks diagonal D ). Informasi yang kami miliki tentang C mengatakan bahwa satu atau lebih elemen diagonal tersebut adalah nol - tetapi itu tidak akan memengaruhi operasi selanjutnya, juga tidak akan mencegah SVD untuk dikomputasi.VD2D2DC
Menghasilkan nilai acak multivarian
Misalkan memiliki standar distribusi normal multivariat: masing-masing komponen memiliki mean nol, Unit varians, dan semua covariances adalah nol: matriks kovarians adalah identitas saya . Kemudian variabel acak Y = V D XXIY=VDX memiliki matriks kovarians
Cov(Y)=E(YY′)=E(VDXX′D′V′)=VDE(XX′)DV′=VDIDV′=VD2V′=C.
Akibatnya variabel acak memiliki distribusi normal multivariat dengan mean μ dan matriks kovarian Cμ+YμC .
Kode Komputasi dan Contoh
R
Kode berikut menghasilkan matriks kovarians dari dimensi dan peringkat yang diberikan, menganalisisnya dengan SVD (atau, dalam kode komentar, dengan komposisi eigend), menggunakan analisis tersebut untuk menghasilkan sejumlah realisasi ditentukan (dengan vektor rata-rata 0 ) , dan kemudian membandingkan matriks kovarians dari data tersebut dengan matriks kovarians yang dituju baik secara numerik dan grafik. Seperti ditunjukkan, itu menghasilkan 10 , 000 realisasi mana dimensi Y adalah 100 dan pangkat C adalah 50Y010,000Y100C50 . Outputnya adalah
rank L2
5.000000e+01 8.846689e-05
Artinya, peringkat data juga dan matriks kovarians seperti yang diperkirakan dari data berada dalam jarak 8 × 10 - 5 dari C - yang dekat. Sebagai pemeriksaan yang lebih terperinci, koefisien C diplot terhadap perkiraannya. Mereka semua berada dekat dengan garis kesetaraan:508×10−5CC
Kode tersebut persis paralel dengan analisis sebelumnya dan karenanya harus jelas (bahkan untuk non- R
pengguna, yang mungkin meniru di lingkungan aplikasi favorit mereka). Satu hal yang diungkapkan adalah perlunya kehati-hatian ketika menggunakan algoritma floating-point: entri dapat dengan mudah menjadi negatif (tapi kecil) karena ketidaktepatan. Entri seperti itu perlu di-nolkan sebelum menghitung akar kuadrat untuk menemukan D itu sendiri.D2D
n <- 100 # Dimension
rank <- 50
n.values <- 1e4 # Number of random vectors to generate
set.seed(17)
#
# Create an indefinite covariance matrix.
#
r <- min(rank, n)+1
X <- matrix(rnorm(r*n), r)
C <- cov(X)
#
# Analyze C preparatory to generating random values.
# `zapsmall` removes zeros that, due to floating point imprecision, might
# have been rendered as tiny negative values.
#
s <- svd(C)
V <- s$v
D <- sqrt(zapsmall(diag(s$d)))
# s <- eigen(C)
# V <- s$vectors
# D <- sqrt(zapsmall(diag(s$values)))
#
# Generate random values.
#
X <- (V %*% D) %*% matrix(rnorm(n*n.values), n)
#
# Verify their covariance has the desired rank and is close to `C`.
#
s <- svd(Sigma <- cov(t(X)))
(c(rank=sum(zapsmall(s$d) > 0), L2=sqrt(mean(Sigma - C)^2)))
plot(as.vector(C), as.vector(Sigma), col="#00000040",
xlab="Intended Covariances",
ylab="Estimated Covariances")
abline(c(0,1), col="Gray")