Genere números aleatorios normalmente distribuidos con matriz de covarianza no positiva definida

15

Calculé la matriz de covarianza de la muestra de una muestra y obtuve una matriz simétrica. Con , me gustaría crear -variate rn distribuido normal, pero por lo tanto necesito la descomposición de Cholesky de . ¿Qué debo hacer si no es definitivo positivo?CCnorteCC

Klaus
fuente
1
¿Cuál es la diferencia con esta pregunta stackoverflow.com/questions/17295627/… ?
dickoa
1
Las matrices semidefinidas positivas tienen múltiples raíces cuadradas (consulte la explicación al final de stats.stackexchange.com/a/71303/919 , por ejemplo). No necesariamente necesita el producido por la descomposición de Cholesky. Ahí radica el corazón del problema: encuentre un método para calcular raíces cuadradas que funcione incluso cuando la matriz es singular. @amoeba El título sugiere que su interpretación es correcta.
whuber

Respuestas:

8

Las preocupaciones de interrogación cómo generar variables aleatorias al azar de una distribución normal multivariante con una (posiblemente) singular matriz de covarianza C . Esta respuesta explica una forma que funcionará para cualquier matriz de covarianza. Proporciona una Rimplementación que prueba su precisión.


Análisis algebraico de la matriz de covarianza.

Como C es una matriz de covarianza, es necesariamente simétrica y semidefinida positiva. Para completar la información de fondo, dejemos que μ sea ​​el vector de los medios deseados.

Debido a que es simétrica, su descomposición de valor singular (SVD) y su descomposición propia tendrán automáticamente la formaC

C=Vre2V

para alguna matriz ortogonal y matriz diagonal D 2 . En general, los elementos diagonales de D 2 no son negativos (lo que implica que todos tienen raíces cuadradas reales: elija los positivos para formar la matriz diagonal D ). La información que tenemos sobre C dice que uno o más de esos elementos diagonales son cero, pero eso no afectará ninguna de las operaciones posteriores ni impedirá que se calcule la SVD.Vre2re2reC

Generando valores aleatorios multivariados

Let tiene una distribución normal multivariante estándar: cada componente tiene media cero, varianza unitaria, y todas las covarianzas son cero: su matriz de covarianza es la identidad I . Entonces la variable aleatoria Y = V D X tiene una matriz de covarianzaXyoY=VreX

Cov(Y)=E(YY)=E(VDXXDV)=VDE(XX)DV=VDIDV=VD2V=C.

En consecuencia, la variable aleatoria tiene una distribución normal multivariante con media μ y matriz de covarianza C .μ+YμC

Cálculo y código de ejemplo

El siguiente Rcódigo genera una matriz de covarianza de dimensiones y rangos dados, la analiza con la SVD (o, en el código comentado, con una descomposición propia), usa ese análisis para generar un número específico de realizaciones de (con el vector medio 0 ) , y luego compara la matriz de covarianza de esos datos con la matriz de covarianza prevista, tanto numérica como gráficamente. Como se muestra, genera 10 , 000 realizaciones donde la dimensión de Y es 100 y el rango de C es 50 . La salida esY010,000Y100C50

        rank           L2 
5.000000e+01 8.846689e-05 

Es decir, el rango de los datos también es y la matriz de covarianza estimada a partir de los datos se encuentra a una distancia de 8 × 10 - 5 de C --que está cerca. Como una verificación más detallada, los coeficientes de C se grafican contra los de su estimación. Todos se encuentran cerca de la línea de igualdad:508×105CC

Figura

El código es exactamente paralelo al análisis anterior y, por lo tanto, debe explicarse por sí mismo (incluso para los no Rusuarios, que podrían emularlo en su entorno de aplicación favorito). Una cosa que revela es la necesidad de precaución cuando se utilizan algoritmos de punto flotante: las entradas de pueden ser fácilmente negativas (pero pequeñas) debido a la imprecisión. Dichas entradas deben ponerse a cero antes de calcular la raíz cuadrada para encontrar D en sí.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")
whuber
fuente
2
+1 pero cuando dices "indefinido" en tu primera oración, ¿qué quieres decir exactamente? Revisé en Wikipedia y dice que semidefinito positivo no es indefinido, es decir, indefinido significa que C tiene valores propios positivos y negativos. ¿Eso es lo que quieres decir allí?
ameba dice Reinstate Monica
2
@amoeba Sí, eso fue un error. Gracias por notarlo. "Indefinido" significa que la firma de la matriz tiene signos positivos y negativos, mientras que "semidefinido" significa que la firma tiene un solo signo.
whuber
6

Método de solución A :

  1. 0.5(C+CT)
  2. D+(mmin(eigenvalue(D)))I

En MATLAB, el código sería

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

Método de solución B : Formule y resuelva un SDP convexo (Programa semidefinido) para encontrar la matriz D a C más cercana de acuerdo con la norma frobenius de su diferencia, de modo que D sea positivo definido, habiendo especificado un valor propio mínimo m.

Usando CVX bajo MATLAB, el código sería:

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

Comparación de los métodos de solución : además de simular la matriz inicial, el método de solución A ajusta (aumenta) solo los elementos diagonales en una cantidad común y deja los elementos fuera de la diagonal sin cambios. El método de solución B encuentra la matriz definida positiva más cercana (a la matriz original) que tiene el valor propio mínimo especificado, en el sentido de la norma mínima de frobenio de la diferencia de la matriz definida positiva D y la matriz original C, que se basa en las sumas de diferencias al cuadrado de todos los elementos de D - C, para incluir los elementos fuera de la diagonal. Por lo tanto, al ajustar los elementos fuera de la diagonal, puede reducir la cantidad en la que los elementos diagonales deben aumentarse, y los elementos de diagoan no necesariamente se incrementan en la misma cantidad.

Mark L. Stone
fuente
2

Comenzaría por pensar en el modelo que está estimando.

Si una matriz de covarianza no es semi-definida positiva, puede indicar que tiene un problema de colinealidad en sus variables que indicaría un problema con el modelo y no necesariamente debe resolverse mediante métodos numéricos.

Si la matriz no es positiva semidefinida por razones numéricas, entonces hay algunas soluciones que se pueden leer aquí.

johneric
fuente
1
La suposición es que el modelo es un modelo mixto lineal. Y para este caso no es relevante encontrar un modelo correcto para los datos, sino que los datos se dan como un ejemplo para algunos cálculos. Ahora existe la posibilidad de que obtenga una matriz semidefinida no positiva como estimación de la covaraince. Entonces, qué hacer a partir de ahí, si quiero averiguar la covarianza de la población distribuida normal de donde provienen los datos. Que la muestra esté distribuida normalmente es la suposición.
Klaus
1

Una forma sería calcular la matriz a partir de una descomposición de valores propios. Ahora admitiré que no sé demasiado de las matemáticas detrás de estos procesos, pero de mi investigación parece fructífero mirar este archivo de ayuda:

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

y algunos otros comandos relacionados en R.

Además, consulte 'nearPD' en el paquete Matrix.

Lo siento, no podría ser de más ayuda, pero espero que mi búsqueda pueda ayudarlo a tomar la dirección correcta.

Frank P.
fuente
Hola, gracias por los enlaces. Con respecto a la descomposición del valor propio, esta descomposición no ayuda, porque a partir de ahí se obtienen valores propios complejos para la matriz de raíz cuadrada, pero necesito una matriz con valor de reel.
Klaus
1

Puede obtener los resultados de la función nearPD en el paquete Matrix en R. Esto le devolverá una matriz valorada real.

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
Dr. Mike
fuente
Para los usuarios de R .. esto podría no ser una mala versión de "pobre" (con menos control) del Método de Solución B en mi respuesta.
Mark L. Stone el
Estoy de acuerdo en que esto no es óptimo, pero a veces funciona.
Dr. Mike