Utilizo la descomposición de Cholesky para simular variables aleatorias correlacionadas dada una matriz de correlación. La cuestión es que el resultado nunca reproduce la estructura de correlación tal como se da. Aquí hay un pequeño ejemplo en Python para ilustrar la situación.
import numpy as np
n_obs = 10000
means = [1, 2, 3]
sds = [1, 2, 3] # standard deviations
# generating random independent variables
observations = np.vstack([np.random.normal(loc=mean, scale=sd, size=n_obs)
for mean, sd in zip(means, sds)]) # observations, a row per variable
cor_matrix = np.array([[1.0, 0.6, 0.9],
[0.6, 1.0, 0.5],
[0.9, 0.5, 1.0]])
L = np.linalg.cholesky(cor_matrix)
print(np.corrcoef(L.dot(observations)))
Esto imprime:
[[ 1. 0.34450587 0.57515737]
[ 0.34450587 1. 0.1488504 ]
[ 0.57515737 0.1488504 1. ]]
Como puede ver, la matriz de correlación estimada post-hoc difiere drásticamente de la anterior. ¿Hay algún error en mi código o hay alguna alternativa para usar la descomposición de Cholesky?
Editar
Perdón por este desastre. No pensé que hubiera un error en el código y / o en la forma en que se aplicó la descomposición de Cholesky debido a algunos malentendidos del material que había estudiado antes. De hecho, estaba seguro de que el método en sí no estaba destinado a ser preciso y había estado de acuerdo con eso hasta la situación que me hizo publicar esta pregunta. Gracias por señalar el error que tuve. He editado el título para reflejar mejor la situación real propuesta por @Silverfish.
fuente
Respuestas:
El enfoque basado en la descomposición de Cholesky debería funcionar, se describe aquí y se muestra en la respuesta de Mark L. Stone publicado casi al mismo tiempo que esta respuesta.
Ejemplo en
R
(lo siento, no estoy usando el mismo software que usaste en la pregunta):También te puede interesar esta publicación y esta publicación .
fuente
Es probable que la gente encuentre su error mucho más rápido si explica lo que hizo con palabras y álgebra en lugar de código (o al menos escribirlo con pseudocódigo).
Parece que estás haciendo el equivalente de esto (aunque posiblemente transpuesto):
Lo que debes hacer es esto:
Hay muchas explicaciones de este algoritmo en el sitio. p.ej
¿Cómo generar números aleatorios correlacionados (medias, variaciones y grado de correlación dados)?
¿Puedo usar el método Cholesky para generar variables aleatorias correlacionadas con la media dada?
Éste lo discute directamente en términos de la matriz de covarianza deseada, y también proporciona un algoritmo para obtener una covarianza de muestra deseada :
Generando datos con una matriz de covarianza de muestra dada
fuente
No hay nada malo con la factorización de Cholesky. Hay un error en su código. Ver edición a continuación.
Aquí está el código y los resultados de MATLAB, primero para n_obs = 10000 como lo ha hecho, luego para n_obs = 1e8. Para simplificar, ya que no afecta los resultados, no me molesto con los medios, es decir, los hago ceros. Tenga en cuenta que el chol de MATLAB produce un factor de Cholesky triangular superior R de la matriz M tal que R '* R = M. numpy.linalg.cholesky produce un factor de Cholesky triangular inferior, por lo que se necesita un ajuste en función de mi código; pero creo que su código está bien en ese sentido.
Editar: encontré tu error. Usted aplicó incorrectamente la desviación estándar. Esto es el equivalente de lo que hiciste, lo cual está mal.
fuente
El CV no se trata de código, pero me intrigó ver cómo se vería esto después de todas las buenas respuestas, y específicamente la contribución de @Mark L. Stone. La respuesta real a la pregunta se proporciona en su publicación (acredite su publicación en caso de duda). Estoy moviendo esta información adjunta aquí para facilitar la recuperación de esta publicación en el futuro. Sin restarle importancia a ninguna de las otras respuestas excelentes, después de la respuesta de Mark, esto cierra el problema corrigiendo la publicación en el OP.
Fuente
En Python:
EN [R]:
fuente
Como otros ya han demostrado: cholesky funciona. Aquí una pieza de código que es muy corta y muy cercana al pseudocódigo: una pieza de código en MatMate:
fuente