Ini adalah kode yang diperluas dengan jawaban lama saya pindah ke sini dari utas lainnya .
Saya telah melakukan perhitungan waktu yang lama dari matriks simetris kuadrat dari jarak Mahalanobis berpasangan di SPSS melalui pendekatan matriks topi menggunakan penyelesaian sistem persamaan linear (untuk itu lebih cepat daripada membalikkan matriks kovarians).
Saya bukan pengguna R jadi saya baru saja mencoba mereproduksi @ahfoss ' resep ini di sini di SPSS bersama dengan resep "saya", pada data 1000 kasus dengan 400 variabel, dan saya menemukan cara saya jauh lebih cepat.
H
H (n-1)X ( X′X )- 1X′X
Jadi, kolom tengah dari matriks data, hitung matriks topi, kalikan dengan (n-1), dan lakukan operasi yang berlawanan dengan pemusatan ganda. Anda mendapatkan matriks jarak Mahalanobis kuadrat.
hh2h1h2cos
Dalam pengaturan kami, matriks "double-centrate" secara khusus adalah matriks topi (dikalikan dengan n-1), bukan produk skalar euclidean, dan dengan demikian matriks jarak kuadrat yang dihasilkan adalah matriks jarak Mahalanobis kuadrat, bukan matriks jarak euclidean kuadrat.
HH (n-1)H= {H,H,...}
D2m a h a l= H+ H′- 2 H ( n - 1 )
Kode dalam SPSS dan probe kecepatan di bawah ini.
Kode pertama ini sesuai dengan fungsi @ahfoss fastPwMahal
dari jawaban yang dikutip . Ini setara dengan itu secara matematis. Tapi saya menghitung matriks simetris lengkap jarak (melalui operasi matriks) sementara @ahfoss menghitung segitiga matriks simetris (elemen demi elemen).
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
Berikut ini adalah modifikasi saya untuk membuatnya lebih cepat:
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