Đây là phần mở rộng với mã câu trả lời cũ của tôi được chuyển đến đây từ một chủ đề khác .
Tôi đã thực hiện một tính toán trong một thời gian dài của một ma trận đối xứng vuông có khoảng cách Mahalanobis theo cặp trong SPSS thông qua cách tiếp cận ma trận mũ bằng cách giải hệ phương trình tuyến tính (vì nó nhanh hơn so với đảo ngược ma trận hiệp phương sai).
Tôi không phải là người dùng R nên tôi đã thử sao chép @ahfoss ' công thức này ở đây trong SPSS cùng với công thức "của tôi", trên dữ liệu 1000 trường hợp bằng 400 biến và tôi đã tìm thấy cách của mình nhanh hơn đáng kể.
H
Định nghĩaH (n-1)X ( X'X )- 1X'X
Vì vậy, các cột trung tâm của ma trận dữ liệu, tính toán ma trận mũ, nhân với (n-1) và thực hiện thao tác ngược lại với định tâm kép. Bạn có được ma trận khoảng cách Mahalanobis bình phương.
hh2h1h2cos
Trong cài đặt của chúng tôi, ma trận "nhân đôi" đặc biệt là ma trận mũ (nhân với n-1), không phải là các sản phẩm vô hướng euclide và ma trận khoảng cách bình phương kết quả là ma trận khoảng cách Mahalanobis bình phương, không phải ma trận khoảng cách euclide bình phương.
Trong ký hiệu ma trận: Gọi là đường chéo của H ( n - 1 ) , một vectơ cột. Tuyên truyền cột vào ma trận vuông : ; rồi D 2HH (n-1)H= {H,H,...}
D2m a h a l= H+ H'- 2 H ( n - 1 )
Mã trong SPSS và đầu dò tốc độ bên dưới.
Mã đầu tiên này tương ứng với chức năng @ahfoss fastPwMahal
của câu trả lời được trích dẫn . Nó tương đương với nó về mặt toán học. Nhưng tôi đang tính toán ma trận đối xứng hoàn toàn của khoảng cách (thông qua các phép toán ma trận) trong khi @ahfoss tính toán một tam giác của ma trận đối xứng (yếu tố theo yếu tố).
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
Sau đây là sửa đổi của tôi về nó để làm cho nó nhanh hơn:
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
Cuối cùng là "phương pháp ma trận mũ". Đối với tốc độ, tôi đang tính toán ma trận mũ (các dữ liệu phải được tập trung đầu tiên) 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