이것은 이전 답변이 다른 스레드 에서 여기로 이동 한 코드로 확장되었습니다 .
나는 선형 방정식 시스템의 해법을 사용 하는 모자 매트릭스 접근법을 통해 SPSS에서 페어 단위 Mahalanobis 거리의 사각형 대칭 행렬을 오랫동안 계산해 왔습니다 (공분산 행렬의 반전보다 빠릅니다).
나는 R 사용자가 아니기 때문에 SPSS에서 @ahfoss ' 이 레시피 를 "my"레시피와 함께 1000 건의 400 변수에 대한 데이터에 재현하려고 시도했으며 상당히 빠른 길을 찾았습니다.
pairwise Mahalanobis 거리의 전체 행렬을 계산하는 가장 빠른 방법은 hat matrix 입니다. 즉, 매우 빠른 행렬 곱셈 및 반전 함수가 내장 된 고급 언어 (예 : R)를 사용하는 경우 루프가 전혀 필요하지 않으며 사례 별 루프를 수행하는 것보다 빠릅니다.H
정의 . 제곱 쌍 단위의 마할 라 노비스 거리 의 이중 중심 행렬은 과 같습니다. 여기서 모자 행렬은 열 중심에서 계산 된 . 데이터 .X ( X ' X ) - 1 X ' XH (n-1)X ( X'X )− 1엑스'엑스
따라서 데이터 행렬의 중심 열, 모자 행렬을 계산하고 (n-1)을 곱하고 이중 중심과 반대되는 연산을 수행합니다. 제곱 된 Mahalanobis 거리의 행렬을 얻습니다.
"Double centering"은 유클리드 및 Mahalanobis와 같은 제곱 거리를 데이터 클라우드 의 기하학적 중심 에서 정의 된 스칼라 곱 으로 기하학적으로 정확하게 변환하는 것입니다 . 이 연산은 암묵적으로 코사인 정리를 기반으로합니다 . 다변량 데이터 구멍 사이의 제곱 유클리드 거리 행렬이 있다고 가정합니다. 넌 (다변량 평균) 클라우드의 중심을 찾아 해당 내적 (내적)에 의해 각 페어의 거리를 바꿀이를 거리에 기초 링크에 도시 된 바와 같이, s는 중심하고 그 벡터 사이의 각도. 의 스칼라 제품의 매트릭스의 대각선 상에 서서h 2 h 1 h 2 코스hh2h1h2코사인비 대각선 항목입니다. 그런 다음 코사인 정리 공식을 직접 사용하면 "이중 센트 레이트"행렬을 제곱 거리 행렬로 쉽게 변환 할 수 있습니다.
설정에서 "이중 센트 레이트"행렬은 구체적으로 유클리드 스칼라 곱이 아닌 모자 행렬 (n-1을 곱한 값)이므로 결과 제곱 거리 행렬은 제곱 유클리드 거리 행렬이 아닌 제곱 마할 라 노비스 거리 행렬입니다.
행렬 표기법에서 : 열 벡터 인 의 대각선 이라고하자 . 열을 정사각 행렬로 전파하십시오. ; 그런 다음 .H ( N - 1 ) D 2 m H L = H + H ' - (2) H ( N - 1 )HH (n-1)H= {H,H,...}
디2m a h a l= H+ 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 )− 1엑스'( X'X )− 1엑스'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