Générer des nombres aléatoires normalement distribués avec une matrice de covariance définie non positive

15

J'ai estimé l'échantillon matrice de covariance d'un échantillon et obtenir une matrice symétrique. Avec C , je voudrais créer -variate rn normale distribuée , mais donc je besoin de la décomposition de Cholesky de . Que dois-je faire si n'est pas défini positif?CCC CnCC

Klaus
la source
1
Quelle est la différence avec cette question stackoverflow.com/questions/17295627/… ?
dickoa
1
Les matrices positives-semi-définies ont plusieurs racines carrées (voir l'explication à la fin de stats.stackexchange.com/a/71303/919 , par exemple). Vous n'avez pas nécessairement besoin de celui produit par la décomposition de Cholesky. C'est là que réside le cœur du problème: trouver une méthode pour calculer les racines carrées qui fonctionne même lorsque la matrice est singulière. @amoeba Le titre suggère que votre interprétation est correcte.
whuber

Réponses:

8

La question porte sur la façon de générer des variables aléatoires à partir d'une distribution normale multivariée avec une matrice de covariance (éventuellement) singulière . Cette réponse explique une manière qui fonctionnera pour n'importe quelle matrice de covariance. Il fournit une implémentation qui teste sa précision.CR


Analyse algébrique de la matrice de covariance

Parce que est une matrice de covariance, elle est nécessairement symétrique et semi-définie positive. Pour compléter les informations de base, soit μ le vecteur des moyennes souhaitées.Cμ

Parce que est symétrique, sa décomposition en valeurs singulières (SVD) et sa décomposition en eigendecomprendront automatiquement la formeC

C=V2V

pour une matrice orthogonale et une matrice diagonale D 2 . En général, les éléments diagonaux de D 2 sont non négatifs (ce qui implique qu'ils ont tous de vraies racines carrées: choisissez les positifs pour former la matrice diagonale D ). Les informations dont nous disposons à propos de C indiquent qu'un ou plusieurs de ces éléments diagonaux sont nuls - mais cela n'affectera aucune des opérations suivantes et n'empêchera pas le calcul du SVD.V22C

Génération de valeurs aléatoires multivariées

Soit une distribution normale à plusieurs variables standard: chaque composant a une moyenne nulle, la variance unitaire et toutes covariances sont égales à zéro: la matrice de covariance est l'identité I . Alors la variable aléatoire Y = V D X a une matrice de covarianceXjeOui=VX

Cov(Oui)=E(OuiOui)=E(VXXV)=VE(XX)V=VjeV=V2V=C.

Par conséquent , la variable aléatoire a une distribution normale à plusieurs variables avec une moyenne μ et la matrice de covariance C .μ+OuiμC

Calcul et exemple de code

Le Rcode suivant génère une matrice de covariance de dimensions et de rangs donnés, l'analyse avec le SVD (ou, dans le code commenté, avec une composition par eigendec), utilise cette analyse pour générer un nombre spécifié de réalisations de (avec le vecteur moyen 0 ) , puis compare la matrice de covariance de ces données à la matrice de covariance prévue à la fois numériquement et graphiquement. Comme on le voit, il génère 10 , 000 réalisations où la dimension de Y est de 100 et le rang de C est 50 . La sortie estOui0dix,000Oui100C50

        rank           L2 
5.000000e+01 8.846689e-05 

Autrement dit, le rang des données est également de et la matrice de covariance estimée à partir des données est à une distance de 8 × 10 - 5 de C - qui est proche. À titre de vérification plus détaillée, les coefficients de C sont comparés à ceux de son estimation. Ils se situent tous près de la ligne de l'égalité:508×dix-5CC

Figure

Le code est exactement parallèle à l'analyse précédente et devrait donc être explicite (même pour les non- Rutilisateurs, qui pourraient l'émuler dans leur environnement d'application préféré). Il révèle une nécessité de prudence lors de l'utilisation d'algorithmes à virgule flottante: les entrées de peuvent facilement être négatives (mais minuscules) en raison de l'imprécision. Ces entrées doivent être remises à zéro avant de calculer la racine carrée pour trouver D lui-même.2

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
la source
2
+1 mais quand vous dites "indéfini" dans votre première phrase, que voulez-vous dire exactement? J'ai vérifié sur Wikipedia et il est dit que semi-défini positif n'est pas indéfini, c'est- à- dire indéfini signifie que C a des valeurs propres positives et négatives. C'est ce que vous voulez dire là-bas?
amibe dit Réintégrer Monica
2
@amoeba Oui, c'était une erreur. Merci d'avoir remarqué. "Indéfini" signifie que la signature de la matrice a à la fois des signes positifs et négatifs, tandis que "semi-définie" signifie que la signature n'a qu'un seul signe.
whuber
6

Méthode de solution A :

  1. 0,5(C+CT)
  2. +(m-mjen(ejegenvunelue()))je

Dans MATLAB, le code serait

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

Méthode de solution B : Formuler et résoudre un SDP convexe (programme semi-défini) pour trouver la matrice D à C la plus proche selon la norme de Frobenius de leur différence, de sorte que D soit défini positif, ayant spécifié la valeur propre minimale m.

En utilisant CVX sous MATLAB, le code serait:

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

Comparaison des méthodes de solution : Outre la symétrisation de la matrice initiale, la méthode de solution A ajuste (augmente) uniquement les éléments diagonaux d'une certaine quantité commune et laisse les éléments hors diagonale inchangés. La méthode de solution B trouve la matrice définie positive la plus proche (de la matrice d'origine) ayant la valeur propre minimale spécifiée, au sens de la norme de Frobenius minimale de la différence entre la matrice définie positive D et la matrice originale C, qui est basée sur les sommes de différences au carré de tous les éléments de D - C, pour inclure les éléments hors diagonale. Ainsi, en ajustant les éléments hors diagonale, cela peut réduire le montant auquel les éléments diagonaux doivent être augmentés, et les éléments diagoanl ne sont pas nécessairement tous augmentés du même montant.

Mark L. Stone
la source
2

Je commencerais par penser au modèle que vous estimez.

Si une matrice de covariance n'est pas semi-définie positive, cela peut indiquer que vous avez un problème de colinéarité dans vos variables qui indiquerait un problème avec le modèle et ne devrait pas nécessairement être résolu par des méthodes numériques.

Si la matrice n'est pas semi-définie positive pour des raisons numériques, alors il y a quelques solutions qui peuvent être lues ici

johneric
la source
1
L'hypothèse est que le modèle est un modèle mixte linéaire. Et dans ce cas, il n'est pas pertinent de trouver un modèle correct pour les données, mais plutôt les données sont données à titre d'exemple pour certains calculs. Il y a maintenant la possibilité que vous obteniez une matrice semi-définie non positive comme estimation de la covaraince. Alors, que faire à partir de là, si je veux comprendre la covariance de la population distribuée normale d'où proviennent les données. Que l'échantillon soit distribué normalement est l'hypothèse.
Klaus
1

Une façon serait de calculer la matrice à partir d'une décomposition de valeurs propres. Maintenant, je dois admettre que je ne connais pas trop les mathématiques derrière ces processus, mais d'après mes recherches, il semble utile de consulter ce fichier d'aide:

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

et quelques autres commandes connexes dans R.

Consultez également «nearPD» dans le package Matrix.

Désolé, je n'ai pas pu vous aider davantage, mais j'espère que ma recherche autour de vous pourra vous aider à vous orienter dans la bonne direction.

Frank P.
la source
Salut, merci pour les liens. En ce qui concerne la décomposition des valeurs propres, cette décomposition n'aide pas, car à partir de là, vous obtenez des valeurs propres complexes pour la matrice de racine carrée, mais j'ai besoin d'une matrice à valeur réelle.
Klaus
1

Vous pouvez obtenir les résultats de la fonction nearPD dans le package Matrix dans R. Cela vous donnera une vraie matrice de valeur.

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
la source
Pour les utilisateurs de R .. ce n'est peut-être pas une mauvaise version "pauvre" (avec moins de contrôle) de la méthode de solution B dans ma réponse.
Mark L. Stone
Je suis d'accord que ce n'est pas optimal mais parfois ça fait l'affaire.
Dr Mike