Ceci est le code étendu de mon ancienne réponse déplacé ici à partir d'un autre fil .
Je fais depuis longtemps le calcul d'une matrice symétrique carrée de distances de Mahalanobis par paire dans SPSS via un approche de matrice de chapeau en utilisant la résolution d'un système d'équations linéaires (car c'est plus rapide que l'inversion de la matrice de covariance).
Je ne suis pas un utilisateur R donc j'ai juste essayé de reproduire cette recette @ahfoss ici dans SPSS avec "ma" recette, sur une donnée de 1000 cas par 400 variables, et j'ai trouvé mon chemin beaucoup plus rapidement.
H
H(n−1)X(X′X)−1X′X
Ainsi, centrez les colonnes de la matrice de données, calculez la matrice chapeau, multipliez par (n-1) et effectuez l'opération à l'opposé du double-centrage. Vous obtenez la matrice des distances de Mahalanobis au carré.
hh2h1h2cos sont les entrées hors diagonale. Ensuite, en utilisant directement la formule du théorème du cosinus, vous reconvertissez facilement la matrice "double-centrée" en matrice de distance au carré.
Dans nos paramètres, la matrice "double-centrée" est spécifiquement le chapeau matrice (multipliée par n-1), et non les produits scalaires euclidiens, et la matrice de distance carrée résultante est donc la matrice de distance Mahalanobis carrée, pas la matrice de distance euclidienne carrée.
En notation matricielle: Soit la diagonale de H ( n - 1 ) , vecteur de colonne. Propager la colonne dans la matrice carrée: ; ensuiteHH(n−1)H= {H,H,...}
D2mahal=H+H′−2H(n−1) .
Le code dans SPSS et sonde de vitesse est ci-dessous.
Ce premier code correspond à la fonction @ahfoss fastPwMahal
de la réponse citée . C'est l'équivalent mathématiquement. Mais je calcule la matrice symétrique complète des distances (via les opérations matricielles) tandis que @ahfoss a calculé un triangle de la matrice symétrique (élément par élément).
matrix. /*Matrix session in SPSS;
/*note: * operator means matrix multiplication, &* means usual, elementwise multiplication.
get data. /*Dataset 1000 cases x 400 variables
!cov(data%cov). /*compute usual covariances between variables [this is my own matrix function].
comp icov= inv(cov). /*invert it
call svd(icov,u,s,v). /*svd
comp isqrcov= u*sqrt(s)*t(v). /*COV^(-1/2)
comp Q= data*isqrcov. /*Matrix Q (see ahfoss answer)
!seuclid(Q%m). /*Compute 1000x1000 matrix of squared euclidean distances;
/*computed here from Q "data" they are the squared Mahalanobis distances.
/*print m. /*Done, print
end matrix.
Time elapsed: 3.25 sec
Ce qui suit est ma modification pour le rendre plus rapide:
matrix.
get data.
!cov(data%cov).
/*comp icov= inv(cov). /*Don't invert.
call eigen(cov,v,s2). /*Do sdv or eigen decomposition (eigen is faster),
/*comp isqrcov= v * mdiag(1/sqrt(s2)) * t(v). /*compute 1/sqrt of the eigenvalues, and compose the matrix back, so we have COV^(-1/2).
comp isqrcov= v &* (make(nrow(cov),1,1) * t(1/sqrt(s2))) * t(v). /*Or this way not doing matrix multiplication on a diagonal matrix: a bit faster .
comp Q= data*isqrcov.
!seuclid(Q%m).
/*print m.
end matrix.
Time elapsed: 2.40 sec
Enfin, "l'approche matricielle chapeau". Pour la vitesse, je calcule la matrice du chapeau (les données doivent être centrées en premier) X(X′X)−1X′(X′X)−1X′solve(X'X,X')
matrix.
get data.
!center(data%data). /*Center variables (columns).
comp hat= data*solve(sscp(data),t(data))*(nrow(data)-1). /*hat matrix, and multiply it by n-1 (i.e. by df of covariances).
comp ss= diag(hat)*make(1,ncol(hat),1). /*Now using its diagonal, the leverages (as column propagated into matrix).
comp m= ss+t(ss)-2*hat. /*compute matrix of squared Mahalanobis distances via "cosine rule".
/*print m.
end matrix.
[Notice that if in "comp ss" and "comp m" lines you use "sscp(t(data))",
that is, DATA*t(DATA), in place of "hat", you get usual sq.
euclidean distances]
Time elapsed: 0.95 sec