Genera numeri casuali normalmente distribuiti con matrice di covarianza non definita positiva


15

Ho stimato la matrice di covarianza del campione di un campione e ho ottenuto una matrice simmetrica. Con , vorrei creare -variate rn distribuita normale, ma quindi ho bisogno la decomposizione di Cholesky di . Cosa devo fare se non è definito positivo?C n C CCCnCC


1
Qual è la differenza con questa domanda stackoverflow.com/questions/17295627/… ?
Dickoa,

1
Le matrici semidefinite positive hanno più radici quadrate (vedere la spiegazione alla fine di stats.stackexchange.com/a/71303/919 , per esempio). Non hai necessariamente bisogno di quello prodotto dalla decomposizione di Cholesky. Qui sta il nocciolo del problema: trovare un metodo per calcolare le radici quadrate che funziona anche quando la matrice è singolare. @amoeba Il titolo suggerisce che la tua interpretazione è corretta.
whuber

Risposte:


8

La domanda riguarda come generare variate casuali da una distribuzione normale multivariata con una matrice di covarianza (forse) singolare . Questa risposta spiega un modo che funzionerà per qualsiasi matrice di covarianza. Fornisce un'implementazione che ne verifica l'accuratezza.CR


Analisi algebrica della matrice di covarianza

Poiché è una matrice di covarianza, è necessariamente simmetrica e semidefinita positiva. Per completare le informazioni di base, lasciare essere il vettore di mezzi desiderati. μCμ

Poiché è simmetrico, la sua decomposizione del valore singolare (SVD) e la sua composizione eigend avranno automaticamente la formaC

C=VD2V'

per una matrice ortogonale e una matrice diagonale . In generale, gli elementi diagonali di sono non negativi (implicando che tutti hanno reali radici quadrate: scegli quelli positivi per formare la matrice diagonale ). Le informazioni che abbiamo su dicono che uno o più di quegli elementi diagonali sono zero - ma ciò non influirà su nessuna delle operazioni successive, né impedirà il calcolo dell'SVD.D 2 D 2 D CVD2D2DC

Generazione di valori casuali multivariati

Che abbia una distribuzione normale multivariata standard: ogni componente ha media zero, varianza unitaria e tutte le covarianze sono zero: la sua matrice di covarianza è l'identità . Quindi la variabile casuale ha una matrice di covarianzaI Y = V D XXioY=VDX

Cov(Y)=E(YY')=E(VDXX'D'V')=VDE(XX')DV'=VDioDV'=VD2V'=C.

Di conseguenza la variabile casuale ha una distribuzione normale multivariata con media e matrice di covarianza .μ+YμC

Codice di calcolo ed esempio

Il Rcodice seguente genera una matrice di covarianza di dimensioni e rango dati, analizza con SVD (o, nel codice commentato, con una composizione di eigend), utilizza tale analisi per generare un numero specificato di realizzazioni di (con vettore medio ) , quindi confronta la matrice di covarianza di tali dati con la matrice di covarianza prevista sia numericamente che graficamente. Come mostrato, genera realizzazioni in cui la dimensione di è e il rango di è . L'output èY010,000Y100C50

        rank           L2 
5.000000e+01 8.846689e-05 

Cioè, anche il rango dei dati è e la matrice di covarianza, come stimata dai dati, è a distanza di - che è vicina. Come controllo più dettagliato, i coefficienti di sono tracciati rispetto a quelli della sua stima. Sono tutti vicini alla linea di uguaglianza:508×105CC

figura

Il codice è esattamente parallelo all'analisi precedente e quindi dovrebbe essere autoesplicativo (anche per i non Rutenti, che potrebbero emularlo nel loro ambiente di applicazione preferito). Una cosa che rivela è la necessità di cautela quando si usano algoritmi a virgola mobile: le voci di possono essere facilmente negative (ma minuscole) a causa dell'imprecisione. Tali voci devono essere azzerate prima di calcolare la radice quadrata per trovare stesso.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")

2
+1 ma quando dici "indefinito" nella tua prima frase, cosa intendi esattamente? Ho controllato su Wikipedia e dice che il semidefinito positivo non è indefinito, cioè indefinito significa che C ha autovalori sia positivi che negativi. È quello che vuoi dire lì?
ameba dice di reintegrare Monica il

2
@amoeba Sì, è stato un errore. Grazie per averlo notato. "Indefinito" significa che la firma della matrice ha segni sia positivi che negativi, mentre "semidefinito" significa che la firma ha un solo segno.
whuber

6

Metodo di soluzione A :

  1. 0.5(C+CT)
  2. D+(m-mion(eiogenvun'lue(D)))io

In MATLAB, il codice sarebbe

D = 0.5 * (C + C');
D =  D + (m - min(eig(CD)) * eye(size(D));

Metodo di soluzione B : formulare e risolvere un SDP convesso (programma semidefinito) per trovare la matrice più vicina da D a C secondo la norma frobenius della loro differenza, in modo che D sia definito positivo, avendo specificato autovalore minimo m.

Utilizzando CVX in MATLAB, il codice sarebbe:

n = size(C,1);
cvx_begin
variable D(n,n)
minimize(norm(D-C,'fro'))
D -m *eye(n) == semidefinite(n)
cvx_end

Confronto dei metodi di soluzione : Oltre a simmetrizzare la matrice iniziale, il metodo di soluzione A regola (aumenta) solo gli elementi diagonali di una certa quantità comune e lascia invariati gli elementi off-diagonali. Il metodo di soluzione B trova la matrice definita positiva più vicina (alla matrice originale) avente l'autovalore minimo specificato, nel senso della norma minima frobenius della differenza della matrice definita positiva D e della matrice originale C, che si basa sulle somme di differenze quadrate di tutti gli elementi di D - C, per includere gli elementi fuori diagonale. Quindi, regolando gli elementi fuori diagonale, può ridurre la quantità di cui è necessario aumentare gli elementi diagonali e gli elementi diagoanl non sono necessariamente tutti aumentati della stessa quantità.


2

Vorrei iniziare pensando al modello che stai stimando.

Se una matrice di covarianza non è semi-definita positiva, ciò può indicare che hai un problema di colinearità nelle tue variabili che indicherebbe un problema con il modello e non dovrebbe necessariamente essere risolto con metodi numerici.

Se la matrice non è semidefinita positiva per motivi numerici, allora ci sono alcune soluzioni che possono essere lette qui


1
L'ipotesi è che il modello sia un modello misto lineare. E in questo caso non è rilevante trovare un modello corretto per i dati, piuttosto i dati vengono forniti come esempio per alcuni calcoli. Ora c'è la possibilità di ottenere una matrice semidefinita non positiva come stima per la covaraince. Quindi cosa fare da lì, se voglio capire la covarianza dalla normale popolazione distribuita da cui provengono i dati. Che il campione sia distribuito normalmente è l'assunzione.
Klaus,

1

Un modo sarebbe calcolare la matrice da una decomposizione di autovalori. Ora ammetto che non conosco troppo la matematica dietro questi processi ma dalla mia ricerca sembra fruttuoso guardare questo file di aiuto:

http://stat.ethz.ch/R-manual/R-patched/library/Matrix/html/chol.html

e alcuni altri comandi correlati in R.

Inoltre, controlla 'nearPD' nel pacchetto Matrix.

Mi dispiace, non potrei essere di maggiore aiuto, ma spero che la mia ricerca possa aiutarti a spingerti nella giusta direzione.


Ciao, grazie per i collegamenti. Rispetto alla decomposizione del valore autigenico, questa decomposizione non aiuta, perché da lì si ottengono autovalori complessi per la matrice di radice quadrata, ma ho bisogno di una matrice di valore di riferimento.
Klaus,

1

Puoi ottenere i risultati dalla funzione nearPD nel pacchetto Matrix in R. Questo ti restituirà una matrice di valore reale.

library(Matrix)
A <- matrix(1, 3,3); A[1,3] <- A[3,1] <- 0
n.A <- nearPD(A, corr=T, do2eigen=FALSE)
n.A$mat

# 3 x 3 Matrix of class "dpoMatrix"
#           [,1]      [,2]      [,3]
# [1,] 1.0000000 0.7606899 0.1572981
# [2,] 0.7606899 1.0000000 0.7606899
# [3,] 0.1572981 0.7606899 1.0000000

Per gli utenti di R .. questa potrebbe non essere una cattiva versione di "uomo povero" (con meno controllo) del metodo di soluzione B nella mia risposta.
Mark L. Stone,

Sono d'accordo che questo non è ottimale, ma a volte fa il trucco.
Dr. Mike
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.