Die Frage ist, wie aus einer multivariaten Normalverteilung mit einer (möglicherweise) singulären Kovarianzmatrix Zufallsvariablen erzeugt werden können . Diese Antwort erklärt einen Weg, der für jede Kovarianzmatrix funktioniert . Es bietet eine Implementierung, die die Genauigkeit testet.CR
Algebraische Analyse der Kovarianzmatrix
Da eine Kovarianzmatrix ist, ist sie notwendigerweise symmetrisch und positiv-semidefinit. Um die Hintergrundinformationen zu vervollständigen, sei μ der Vektor des gewünschten Mittels.Cμ
Da symmetrisch ist, haben seine Singular Value Decomposition (SVD) und seine eigendecomposition automatisch die FormC
C=VD2V′
für einige orthogonale Matrix und diagonale Matrix D 2 . Im Allgemeinen sind die diagonalen Elemente von D 2 nichtnegativ (was bedeutet, dass sie alle echte Quadratwurzeln haben: Wählen Sie die positiven aus, um die diagonale Matrix D zu bilden ). Die Informationen, die wir über C haben, besagen, dass eines oder mehrere dieser diagonalen Elemente Null sind - dies hat jedoch keine Auswirkungen auf die nachfolgenden Operationen und verhindert auch nicht, dass die SVD berechnet wird.VD2D2DC
Generierung multivariater Zufallswerte
Es sei eine Standard multivariate Normalverteilung: Jede Komponente hat einen Mittelwert von Null, Einheitsvarianz, und alle Kovarianzen gleich Null sind: seine Kovarianzmatrix die Identität I . Dann wird der Zufallsvariable Y = V D X hat KovarianzmatrixXIY= V D X
Cov( Y) = E ( YY.′) = E ( V D XX′D′V′) = V D E ( XX′) D V′= V D I D V′= V D2V′= C .
Folglich ist die Zufallsvariable hat eine multivariate Normalverteilung mit Mittelwert μ und die Kovarianzmatrix C .μ + YμC
Berechnungs- und Beispielcode
Der folgende R
Code generiert eine Kovarianzmatrix mit den angegebenen Dimensionen und Rängen, analysiert sie mit der SVD (oder verwendet diese Analyse im auskommentierten Code mit einer Neukomposition), um eine bestimmte Anzahl von Realisierungen von (mit dem Mittelwertvektor 0 ) zu generieren. und vergleicht dann die Kovarianzmatrix dieser Daten sowohl numerisch als auch grafisch mit der beabsichtigten Kovarianzmatrix. Wie gezeigt, erzeugt sie 10 , 000 Realisierungen wo die Dimension Y ist 100 , und der Rang C ist 50 . Die Ausgabe istY.010 , 000Y.100C50
rank L2
5.000000e+01 8.846689e-05
Das heißt, dass der Rang der Daten auch und die Kovarianzmatrix wie aus den Daten geschätzt ist innerhalb Abstand 8 × 10 - 5 von C --which nahe ist. Zur genaueren Überprüfung werden die Koeffizienten von C gegen die seiner Schätzung aufgetragen. Sie alle liegen nahe an der Linie der Gleichheit:508 × 10- 5CC
Der Code entspricht genau der vorhergehenden Analyse und sollte daher selbsterklärend sein (auch für Nichtbenutzer R
, die ihn möglicherweise in ihrer bevorzugten Anwendungsumgebung emulieren). Es zeigt sich, dass bei der Verwendung von Gleitkomma-Algorithmen Vorsicht geboten ist: Die Eingaben von können aufgrund von Ungenauigkeiten leicht negativ (aber winzig) sein. Solche Einträge müssen auf Null gesetzt werden, bevor die Quadratwurzel berechnet wird, um D selbst zu finden .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")