Je voudrais générer une matrice de corrélation aléatoire de telle sorte qu'il y ait des corrélations modérément fortes présentes: n × n
- matrice symétrique réelle carrée de taille, avec par exemple ;n = 100
- positif-défini, c'est-à-dire avec toutes les valeurs propres réelles et positives;
- rang complet;
- tous les éléments diagonaux égaux à ;
- les éléments hors diagonale doivent être répartis de manière raisonnablement uniforme sur . La distribution exacte n'a pas d'importance, mais j'aimerais avoir une quantité modérément grande (par exemple ) de valeurs modérément grandes (par exemple avec une valeur absolue de ou plus). Fondamentalement, je veux m'assurer que n'est pas presque en diagonale avec tous les éléments hors diagonale .10 % 0,5 C
Existe-t-il un moyen simple de le faire?
Le but est d'utiliser de telles matrices aléatoires pour comparer certains algorithmes travaillant avec des matrices de corrélation (ou covariance).
Méthodes qui ne fonctionnent pas
Voici quelques façons de générer des matrices de corrélation aléatoires que je connais, mais qui ne fonctionnent pas pour moi ici:
Générer au hasard de dimensions, du centre, de normaliser et de former la matrice de corrélation . Si , cela se traduira généralement par toutes les corrélations hors diagonale autour de . Si , certaines corrélations seront fortes, mais ne sera pas de rang complet. s × n C = 1s>n0s≪nC
Générez une matrice définie positive aléatoire de l'une des manières suivantes:
Générez un carré aléatoire et symétrique positif défini .B = A A ⊤
Générer un carré aléatoire , rendre symétrique et le rendre positif défini en effectuant la décomposition propre et mettre toutes les valeurs propres négatives à zéro: . NB: cela se traduira par une matrice de rang déficient.E = A + A ⊤ E = U S U ⊤ B = U
Générer aléatoire orthogonal (par exemple en générant un carré aléatoire et en faisant sa décomposition QR, ou via le processus de Gram-Schmidt) et aléatoire diagonal avec tous les éléments positifs; forme .
La matrice obtenue peut être facilement normalisée pour avoir toutes celles sur la diagonale: , où est la matrice diagonale avec la même diagonale que . Les trois méthodes répertoriées ci-dessus pour générer résultat que des éléments hors diagonale fermant .
Mise à jour: anciens threads
Après avoir posté ma question, j'ai trouvé deux doublons dans le passé:
- Comment générer une matrice de corrélation aléatoire qui a des entrées hors diagonale approximativement normalement distribuées avec un écart-type donné?
- Comment générer efficacement des matrices de corrélations positives-semi-finies aléatoires?
Malheureusement, aucun de ces fils ne contenait de réponse satisfaisante (jusqu'à présent :)
la source
nXk
matrice de chargement W, pas entièrement aléatoire, mais celle que nous voulons (elleWW'+diag(noise)
définira la matrice cov que nous recherchons. La seule tâche est de corriger le W normalisé par colonne (c'est-à-dire le k "vecteurs propres") pour devenir orthogonaux. Toute méthode pour décorréler les variables corrélées (ici les variables sont les vecteurs propres) fera probablement l'affaire. (C'est une idée brute.)Réponses:
D'autres réponses ont fourni de belles astuces pour résoudre mon problème de différentes manières. Cependant, j'ai trouvé une approche fondée sur des principes qui, je pense, a un grand avantage d'être conceptuellement très claire et facile à ajuster.
Dans ce fil de discussion: Comment générer efficacement des matrices de corrélation aléatoire semi-définies positives? - J'ai décrit et fourni le code de deux algorithmes efficaces de génération de matrices de corrélation aléatoire. Tous deux proviennent d'un article de Lewandowski, Kurowicka et Joe (2009), auquel @ssdecontrol a fait référence dans les commentaires ci-dessus (merci beaucoup!).
S'il vous plaît voir ma réponse là pour beaucoup de chiffres, d'explications et de code matlab. La méthode dite de "vigne" permet de générer des matrices de corrélation aléatoires avec n'importe quelle distribution de corrélations partielles et peut être utilisée pour générer des matrices de corrélation avec de grandes valeurs hors diagonales. Voici l'exemple de figure de ce fil:
La seule chose qui change entre les sous-parcelles est un paramètre qui contrôle la concentration de la distribution des corrélations partielles autour de .± 1
Je copie mon code pour générer ces matrices ici aussi, pour montrer qu'il n'est pas plus long que les autres méthodes suggérées ici. Veuillez voir ma réponse liée pour quelques explications. Les valeurs de50 , 20 , 10 , 5 , 2 , 1 100
betaparam
pour la figure ci-dessus étaient (et la dimensionnalité était de 100 ).d
Mise à jour: valeurs propres
@psarka pose des questions sur les valeurs propres de ces matrices. Sur la figure ci-dessous, je trace les spectres de valeurs propres des six mêmes matrices de corrélation que ci-dessus. Notez qu'ils diminuent progressivement; en revanche, la méthode suggérée par @psarka aboutit généralement à une matrice de corrélation avec une grande valeur propre, mais le reste étant assez uniforme.
Mise à jour. Méthode vraiment simple: plusieurs facteurs
Semblable à ce que @ttnphns a écrit dans les commentaires ci-dessus et à @GottfriedHelms dans sa réponse, un moyen très simple d'atteindre mon objectif est de générer aléatoirement plusieurs ( ) chargements de facteur W (matrice aléatoire de taille k × n ), forment le matrice de covariance W W ⊤ (qui bien sûr ne sera pas de rang complet) et y ajouter une matrice diagonale aléatoire D avec des éléments positifs pour faire B = W W ⊤ + Dk < n W k × n W W⊤ ré B = W W⊤+ D rang complet. La matrice de covariance résultante peut être normalisée pour devenir une matrice de corrélation (comme décrit dans ma question). C'est très simple et fait l'affaire. Voici quelques exemples de matrices de corrélation pour :k = 100 , 50 , 20 , 10 , 5 , 1
Le seul inconvénient est que la matrice résultante aura grandes valeurs propres, puis une chute soudaine, par opposition à une belle désintégration illustrée ci-dessus avec la méthode de la vigne. Voici les spectres correspondants:k
Voici le code:
la source
W
orthogonales (c'est-à-dire que les cosinus entre elles sont 0). La simple génération aléatoireW
ne le fournit bien sûr pas. S'ils ne sont pas orthogonaux - c'est-à-dire que les facteurs sont obliques (appelons alorsW
asW_
) - le théorème des facteurs n'est pasWW'
maisW_CW_'
avec desC
"corrélations" (cosinus) entre les facteurs. Maintenant,C=Q'Q
avecQ
étant la matrice de rotation non orthogonal de rotationW_=inv(Q)'W
(et doncW=W_Q'
). GénérezQ
-en une matrice avec colonne ss = 1 et matrice ss = taille de la matrice.W_=inv(Q)'W
, bien sûrW_= 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))
la source
crs
Hmm, après avoir fait un exemple dans mon langage MatMate, je vois qu'il y a déjà une réponse python, ce qui pourrait être préférable car python est largement utilisé. Mais parce que vous aviez encore des questions, je vous montre mon approche en utilisant le langage Matmate-matrix, c'est peut-être plus auto-commenté.
Méthode 1
(à l'aide de MatMate):
Le problème ici pourrait être que nous définissons des blocs de sous-matrices qui ont de fortes corrélations à l'intérieur avec peu de corrélation entre et ce n'est pas par programme mais par les expressions de concaténation constantes. Peut-être que cette approche pourrait être modélisée plus élégamment en python.
Méthode 2 (a)
Après cela, il y a une approche complètement différente, où nous remplissons la covariance restante possible par des quantités aléatoires de 100 pour cent dans une matrice de charges de facteurs. Cela se fait en Pari / GP:
et la matrice de corrélation produite est
Il est possible que cela génère une matrice de corrélation avec des composants principaux dominants en raison de la règle de génération cumulative pour la matrice de charges factorielles. Il serait également préférable d’assurer un caractère définitif positif en faisant de la dernière partie de la variance un facteur unique. Je l'ai laissé dans le programme pour rester concentré sur le principe général.
Une matrice de corrélation 100x100 avait les fréquences de corrélations suivantes (arrondies à 1 déc.)
[mise à jour]. Hmm, la matrice 100x100 est mal conditionnée; Pari / GP ne peut pas déterminer correctement les valeurs propres avec la fonction polroots (charpoly ()), même avec une précision de 200 chiffres. J'ai fait une rotation de Jacobi pour former pca sur la matrice de chargement L et j'ai trouvé des valeurs propres extrêmement petites, les ai imprimées en logarithmes à la base 10 (qui donnent approximativement la position de la virgule décimale). Lisez de gauche à droite, puis ligne par ligne:
[mise à jour 2]
Méthode 2 (b)
Une amélioration pourrait être d'augmenter la variance spécifique à un élément à un niveau non marginal et de réduire à un nombre raisonnablement plus petit de facteurs communs (par exemple, racine carrée entière du numéro d'article):
La structure du résultat
en termes de distribution des corrélations:
reste similaire (également la non décomposabilité désagréable par PariGP), mais les valeurs propres, lorsqu'elles sont trouvées par jacobi-rotation de la matrice de chargement, ont maintenant une meilleure structure, pour un exemple nouvellement calculé, j'ai obtenu les valeurs propres comme
la source
la source
R a un package (clusterGeneration) qui implémente la méthode dans:
Exemple:
Malheureusement, il ne semble pas possible de simuler des corrélations qui suivent une distribution uniforme avec cela. Il semble faire des corrélations plus fortes quand il
alphad
est réglé sur de très petites valeurs, mais même à1/100000000000000
, la plage de corrélations ne monterait qu'à environ 1,40.Néanmoins, j'espère que cela pourrait être utile à quelqu'un.
la source