J'utilise la décomposition de Cholesky pour simuler des variables aléatoires corrélées étant donné une matrice de corrélation. Le fait est que le résultat ne reproduit jamais la structure de corrélation telle qu'elle est donnée. Voici un petit exemple en Python pour illustrer la situation.
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)))
Cela imprime:
[[ 1. 0.34450587 0.57515737]
[ 0.34450587 1. 0.1488504 ]
[ 0.57515737 0.1488504 1. ]]
Comme vous pouvez le voir, la matrice de corrélation estimée post-hoc diffère radicalement de la précédente. Y a-t-il un bogue dans mon code ou existe-t-il une alternative à l'utilisation de la décomposition Cholesky?
Éditer
Je vous demande pardon pour ce gâchis. Je ne pensais pas qu'il y avait une erreur dans le code et / ou dans la façon dont la décomposition de Cholesky était appliquée en raison d'une mauvaise compréhension du matériel que j'avais étudié auparavant. En fait, j'étais sûr que la méthode elle-même n'était pas censée être précise et j'étais d'accord avec cela jusqu'à la situation qui m'a fait poser cette question. Merci d'avoir souligné l'idée fausse que j'avais. J'ai édité le titre pour mieux refléter la situation réelle proposée par @Silverfish.
la source
Réponses:
L'approche basée sur la décomposition de Cholesky devrait fonctionner, elle est décrite ici et est montrée dans la réponse de Mark L. Stone postée presque en même temps que cette réponse.
Néanmoins, j'ai parfois généré des tirages à partir de la distribution normale multivariée comme suit:N( μ⃗ , Σ )
où sont les tirages finaux, sont des tirages de la distribution normale standard univariée, est une matrice contenant les vecteurs propres normalisés de la matrice cible et est une matrice diagonale contenant les valeurs propres de disposées dans le même ordre comme vecteurs propres dans les colonnes de .X Φ Σ Λ Σ ΦOui X Φ Σ Λ Σ Φ
Exemple dans
R
(désolé, je n'utilise pas le même logiciel que vous avez utilisé dans la question):Vous pouvez également être intéressé par cet article et cet article .
la source
Les gens trouveraient probablement votre erreur beaucoup plus rapidement si vous expliquiez ce que vous avez fait avec des mots et l'algèbre plutôt qu'avec du code (ou du moins l'écrivant en utilisant un pseudocode).
Vous semblez faire l'équivalent de ceci (bien que possiblement transposé):
Ce que vous devez faire est le suivant:
Il existe de nombreuses explications sur cet algorithme sur le site. par exemple
Comment générer des nombres aléatoires corrélés (moyennes, variances et degrés de corrélation donnés)?
Puis-je utiliser la méthode Cholesky pour générer des variables aléatoires corrélées avec une moyenne donnée?
Celui-ci en parle directement en termes de matrice de covariance souhaitée, et donne également un algorithme pour obtenir une covariance d' échantillon souhaitée :
Génération de données avec une matrice de covariance d'échantillon donnée
la source
Il n'y a rien de mal à la factorisation de Cholesky. Il y a une erreur dans votre code. Voir modification ci-dessous.
Voici le code MATLAB et les résultats, d'abord pour n_obs = 10000 comme vous l'avez, puis pour n_obs = 1e8. Pour plus de simplicité, car cela n'affecte pas les résultats, je ne me soucie pas des moyens, c'est-à-dire que je leur fais des zéros. Notez que le chol de MATLAB produit un facteur de Cholesky triangulaire supérieur R de la matrice M tel que R '* R = M. numpy.linalg.cholesky produit un facteur de Cholesky triangulaire inférieur, donc un ajustement par rapport à mon code est nécessaire; mais je crois que votre code est très bien à cet égard.
Edit: j'ai trouvé votre erreur. Vous avez incorrectement appliqué l'écart type. C'est l'équivalent de ce que vous avez fait, ce qui est faux.
la source
CV ne concerne pas le code, mais j'étais intrigué de voir à quoi cela ressemblerait après toutes les bonnes réponses, et en particulier la contribution de @Mark L. Stone. La réponse réelle à la question est fournie sur son message (veuillez créditer son message en cas de doute). Je déplace ces informations jointes ici pour faciliter la récupération de ce message à l'avenir. Sans minimiser aucune des autres excellentes réponses, après la réponse de Mark, cela résout le problème en corrigeant le message dans l'OP.
La source
À PYTHON:
EN [R]:
la source
Comme d'autres l'ont déjà montré: des œuvres cholesky. Voici un bout de code qui est très court et très proche du pseudocode: un codepiece dans MatMate:
la source