Me gustaría generar una matriz de correlación aleatoria de tamaño modo que haya algunas correlaciones moderadamente fuertes presentes:
- matriz simétrica real cuadrada de tamaño , con, por ejemplo, ;
- positivo-definido, es decir, con todos los valores propios reales y positivos;
- rango completo;
- todos los elementos diagonales iguales a ;
- los elementos fuera de la diagonal deben distribuirse razonablemente de manera uniforme en . La distribución exacta no importa, pero me gustaría tener una cantidad moderadamente grande (por ejemplo, ) de valores moderadamente grandes (por ejemplo, con un valor absoluto de o superior). Básicamente quiero para asegurarse de que es no casi diagonal con todos los elementos fuera de la diagonal .
¿Hay una manera simple de hacerlo?
El propósito es usar tales matrices aleatorias para comparar algunos algoritmos que trabajan con matrices de correlación (o covarianza).
Métodos que no funcionan.
Aquí hay algunas formas de generar matrices de correlación aleatorias que conozco, pero que no me funcionan aquí:
Genere azar de tamaño , centre, estandarice y forme la matriz de correlación . Si, esto generalmente dará como resultado que todas las correlaciones fuera de la diagonal estén alrededor de. Si, algunas correlaciones serán fuertes, perono será rango completo.
Genere una matriz definida positiva aleatoria de una de las siguientes maneras:
Genere el cuadrado aleatorio y haga que el simétrico positivo sea definido B = A A ⊤ .
Genere un cuadrado aleatorio , haga simétrico E = A + A ⊤ , y haga que sea positivo definido realizando la descomposición propia E = U S U ⊤ y estableciendo todos los valores propios negativos en cero: B = U . NB: esto dará como resultado una matriz de rango deficiente.
Genere ortogonal aleatorio (por ejemplo, generando un cuadrado aleatorio A y haciendo su descomposición QR, o mediante el proceso de Gram-Schmidt) y diagonal D aleatoria con todos los elementos positivos; forma B = Q D Q ⊤ .
Obtenido matriz puede normalizarse fácilmente tener todos unos en la diagonal: C = D - 1 / 2 B D - 1 / 2 , donde D = delta i un g es la matriz diagonal con la misma diagonal como B . Las tres formas mencionadas anteriormente para generar B dan como resultado que C tenga elementos fuera de la diagonal cerca de 0 .
Actualización: hilos más antiguos
Después de publicar mi pregunta, encontré dos duplicados en el pasado:
- ¿Cómo generar una matriz de correlación aleatoria que tenga entradas fuera de diagonal distribuidas aproximadamente normalmente con una desviación estándar dada?
- ¿Cómo generar de manera eficiente matrices de correlación aleatoria positiva-semidefinida?
Desafortunadamente, ninguno de estos hilos contenía una respuesta satisfactoria (hasta ahora :)
fuente
nXk
matriz de carga W, no completamente aleatoria pero la que queremos (WW'+diag(noise)
definirá la matriz cov que buscamos. La única tarea es corregir la columna normalizada W (es decir, la k "vectores propios") para convertirse ortogonal Cualquier método de de-correlación correlaciona las variables (en este caso las variables son los vectores propios), probablemente hará (Esta idea de una prima)...Respuestas:
Otras respuestas surgieron con buenos trucos para resolver mi problema de varias maneras. Sin embargo, encontré un enfoque basado en principios que creo que tiene una gran ventaja de ser conceptualmente muy claro y fácil de ajustar.
En este hilo: ¿Cómo generar eficientemente matrices de correlación semidefinidas positivas al azar? - Describí y proporcioné el código para dos algoritmos eficientes de generación de matrices de correlación aleatorias. Ambos provienen de un artículo de Lewandowski, Kurowicka y Joe (2009), al que @ssdecontrol se refirió en los comentarios anteriores (¡muchas gracias!).
Consulte mi respuesta allí para ver muchas figuras, explicaciones y códigos matlab. El llamado método "vine" permite generar matrices de correlación aleatorias con cualquier distribución de correlaciones parciales y puede usarse para generar matrices de correlación con grandes valores fuera de la diagonal. Aquí está la figura de ejemplo de ese hilo:
Lo único que cambia entre subtramas es un parámetro que controla cuánto se concentra la distribución de correlaciones parciales alrededor de .± 1
Copio mi código para generar estas matrices aquí también, para mostrar que no es más largo que los otros métodos sugeridos aquí. Por favor vea mi respuesta vinculada para algunas explicaciones. Los valores de50 , 20 , 10 , 5 , 2 , 1 100
betaparam
para la figura anterior fueron (y la dimensionalidad fue 100 ).d
Actualización: valores propios
@psarka pregunta sobre los valores propios de estas matrices. En la figura siguiente, trazo los espectros de valores propios de las mismas seis matrices de correlación que las anteriores. Tenga en cuenta que disminuyen gradualmente; en contraste, el método sugerido por @psarka generalmente da como resultado una matriz de correlación con un valor propio grande, pero el resto es bastante uniforme.
Actualizar. Método realmente simple: varios factores
Aquí está el código:
fuente
W
son ortogonales (es decir, los cosenos entre ellos son 0). Simplemente generar al azar,W
por supuesto, no lo proporciona. Si no son ortogonales, es decir, los factores son oblicuos (llame entoncesW
comoW_
), el teorema del factor no lo esWW'
sinoW_CW_'
con lasC
"correlaciones" (cosenos) entre los factores. Ahora,C=Q'Q
alQ
ser la matriz de rotación de rotación no ortogonalW_=inv(Q)'W
(y asíW=W_Q'
). Genere algunosQ
: una matriz con la columna ss = 1 y la matriz ss = tamaño de la matriz.W_=inv(Q)'W
, por supuestoW_= W inv(Q)'
.W = replicate(k, rnorm(d)); S = W%*%t(W) + diag(rnorm(d),nrow=d); S = diag(1/sqrt(diag(S)))%*%S%*%diag(1/sqrt(diag(S)))
S <- matrix(nearPD(S, corr = TRUE, keepDiag = TRUE)$mat@x,ncol(S),ncol(S))
fuente
crs
Hmm, después de haber hecho un ejemplo en mi lenguaje MatMate, veo que ya hay una respuesta de Python, que podría ser preferible porque Python es ampliamente utilizado. Pero debido a que aún tenía preguntas, le muestro mi enfoque usando el lenguaje de matriz de Matmate, tal vez es más autocomentario.
Método 1
(usando MatMate):
El problema aquí podría ser que definimos bloques de submatrices que tienen altas correlaciones dentro con poca correlación entre y esto no es programáticamente sino por las constantes expresiones de concatenación. Tal vez este enfoque podría modelarse de manera más elegante en Python.
Método 2 (a)
Después de eso, hay un enfoque completamente diferente, donde llenamos la posible covarianza restante por cantidades aleatorias del 100 por ciento en una matriz de carga de factores. Esto se hace en Pari / GP:
y la matriz de correlación producida es
Posiblemente esto genera una matriz de correlación con componentes principales dominantes debido a la regla de generación acumulativa para la matriz de carga de factores. También podría ser mejor asegurar una definición positiva al hacer que la última parte de la varianza sea un factor único. Lo dejé en el programa para mantener el enfoque en el principio general.
Una matriz de correlación de 100x100 tenía las siguientes frecuencias de correlaciones (redondeadas a 1 lugar dec.)
[actualizar]. Hmm, la matriz 100x100 está mal acondicionada; Pari / GP no puede determinar los valores propios correctamente con la función polroots (charpoly ()), incluso con una precisión de 200 dígitos. Hice una rotación de Jacobi para formar pca en la matriz de carga L y encontré valores propios extremadamente pequeños, los imprimí en logaritmos a la base 10 (que dan aproximadamente la posición del punto decimal). Lea de izquierda a derecha y luego fila por fila:
[actualización 2]
Método 2 (b)
Una mejora podría ser aumentar la varianza específica del ítem a un nivel no marginal y reducir a un número razonablemente menor de factores comunes (por ejemplo, la raíz cuadrada entera del número de ítem):
La estructura del resultado.
en términos de distribución de correlaciones:
sigue siendo similar (también la desagradable no descomponibilidad de PariGP), pero los valores propios, cuando se encuentran mediante la rotación jacobi de la matriz de carga, ahora tienen una mejor estructura, para un ejemplo recién calculado obtuve los valores propios como
fuente
Pregunta interesante (como siempre!). ¿Qué tal encontrar un conjunto de matrices de ejemplo que exhiban las propiedades que desea, y luego tomar combinaciones convexas de las mismas, ya que siUNA y si son positivos definidos, entonces también lo es λ A + ( 1 - λ ) B . Como beneficio adicional, no será necesario reescalar las diagonales por la convexidad de la operación. Ajustando elλ para estar más concentrado hacia 0 y 1 versus distribuido uniformemente, podría concentrar las muestras en los bordes del politopo o en el interior. (Podría usar una distribución beta / Dirichlet para controlar la concentración frente a la uniformidad).
Por ejemplo, podrías dejarUNA ser simétrica por componentes y si Sé toeplitz. Por supuesto, siempre puedes agregar otra clasedo , y tomar λUNAA + λsiB + λdodo tal que ∑ λ = 1 y λ ≥ 0 , y así.
fuente
R tiene un paquete (clusterGeneration) que implementa el método en:
Ejemplo:
Desafortunadamente, no parece posible simular correlaciones que sigan una distribución uniforme con esto. Parece hacer correlaciones más fuertes cuando
alphad
se establece en valores muy pequeños, pero incluso en1/100000000000000
el rango de correlaciones solo subiría a aproximadamente 1.40.Sin embargo, espero que esto pueda ser de alguna utilidad para alguien.
fuente