这是我以前的回答从另一个线程移到此处的代码的扩展。
我一直在通过使用线性方程组求解的帽子矩阵方法,对SPSS中成对的马氏距离的平方对称矩阵进行长时间的计算(因为它比协方差矩阵的求逆要快)。
我不是R用户,因此我尝试在SPSS 上将“ ah”的配方与“我的”配方一起在1000个案例中的400个变量的数据上重现,并且我发现自己的方法相当快。
H
高(n−1)X (X′X )− 1X′X
因此,将数据矩阵的中心列,计算帽子矩阵,乘以(n-1)并执行与双中心相反的操作。您将获得平方的马氏距离矩阵。
HH2H1个H2cos
在我们的设置中,“双中心”矩阵特别是帽子矩阵(乘以n-1),而不是欧几里德标量积,因此,平方距离矩阵是平方的Mahalanobis距离矩阵,而不是欧几里德距离矩阵。
H高(n−1)H= {H,H,...}
d2中号一个ħ 一个升= 高+ H′− 2 H(n − 1 )
SPSS和速度探测器中的代码如下。
第一个代码对应于fastPwMahal
所引用答案的 @ahfoss函数。它在数学上等效于它。但是我正在计算距离的完整对称矩阵(通过矩阵运算),而@ahfoss计算了对称矩阵的三角形(逐元素)。
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
以下是我对其进行的修改以使其更快:
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
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