Это расширенный код, мой старый ответ перенесен сюда из другого потока .
Я долгое время занимался вычислением квадратно-симметричной матрицы парных расстояний Махаланобиса в SPSS с помощью матричного подхода с использованием решения системы линейных уравнений (поскольку это быстрее, чем инвертирование ковариационной матрицы).
Я не пользователь R, поэтому я просто попытался воспроизвести этот рецепт @ahfoss здесь, в SPSS, вместе с «моим» рецептом на данных 1000 случаев по 400 переменным, и я нашел свой путь значительно быстрее.
Более быстрый способ расчета полной матрицы попарных расстояний Махаланобиса - через матрицу ЧАС, Я имею в виду, что если вы используете язык высокого уровня (например, R) с довольно быстрыми встроенными функциями умножения матриц и инверсии, вам не понадобятся циклы вообще, и это будет быстрее, чем выполнение регистровых циклов.
Определение . Двойной центрируется матрица квадратов попарных расстояний Махаланобиса равноH (n-1)где матрица шляпы X ( X'Х )- 1Икс', рассчитывается по центру столбца данных Икс,
Таким образом, отцентрируйте столбцы матрицы данных, вычислите головную матрицу, умножьте на (n-1) и выполните операцию, противоположную двойному центрированию. Вы получаете матрицу квадратов расстояний Махаланобиса.
«Двойное центрирование» - это геометрически правильное преобразование квадратов расстояний (таких как Евклидово и Махаланобис) в скалярные произведения, определенные из геометрического центроида облака данных. Эта операция неявно основана на теореме косинуса . Представьте, что у вас есть матрица квадратов евклидовых расстояний между вашими многовариантными точками данных. Вы находите центроид (многовариантное среднее) облака и заменяете каждое попарное расстояние на соответствующее скалярное произведение (точечное произведение), оно основано на расстоянияхчасs к центроиду и углу между этими векторами, как показано в ссылке. час2s стоят на диагонали этой матрицы скалярных произведений и час1час2созявляются недиагональными записями. Затем, используя непосредственно формулу теоремы косинуса, вы легко конвертируете матрицу «двойного центрирования» обратно в матрицу квадратов расстояний.
В наших настройках матрица "двойного центра" - это, в частности, матрица шляпы (умноженная на n-1), а не евклидовы скалярные произведения, и результирующая квадратная матрица расстояний, таким образом, является квадратом матрицы расстояния Махаланобиса, а не квадратом евклидовой матрицы расстояний.
В матричной записи: пусть ЧАС быть диагональю H (n-1)столбец вектор. Распространить столбец в квадратную матрицу H= {H,H,...}
:; тогдаD2м а ч а л= H+ H'- 2 H ( n - 1 ),
Код в SPSS и датчик скорости ниже.
Этот первый код соответствует @ahfoss функции fastPwMahal
из процитировал ответ . Это эквивалентно математически. Но я вычисляю полную симметричную матрицу расстояний (через матричные операции), в то время как @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'Х )- 1Икс' через обобщенное обратное ( 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