Preciso calcular a distância de Mahalanobis da amostra em R entre cada par de observações em uma matriz de covariáveis. Preciso de uma solução que seja eficiente, ou seja, apenas as distâncias sejam calculadas e implementadas preferencialmente em C / RCpp / Fortran etc. Suponho que , a matriz de covariância populacional, seja desconhecida e use a amostra matriz de covariância em seu lugar.n ( n - 1 ) / 2 Σ
Estou particularmente interessado nesta questão, pois parece não haver um método de "consenso" para calcular distâncias pareadas de Mahalanobis em R, ou seja, não é implementado na dist
função nem na cluster::daisy
função. A mahalanobis
função não calcula distâncias aos pares sem trabalho adicional do programador.
Já foi perguntado aqui a distância Pairwise Mahalanobis em R , mas as soluções parecem incorretas.
Aqui está um método correto, mas terrivelmente ineficiente (já que são calculadas distâncias):
set.seed(0)
x0 <- MASS::mvrnorm(33,1:10,diag(c(seq(1,1/2,l=10)),10))
dM = as.dist(apply(x0, 1, function(i) mahalanobis(x0, i, cov = cov(x0))))
Isso é fácil o suficiente para me codificar em C, mas sinto que algo básico deve ter uma solução preexistente. Existe um?
Existem outras soluções que ficam aquém: HDMD::pairwise.mahalanobis()
calcula distâncias, quando apenas distâncias únicas são necessárias. parece promissor, mas não quero que minha função venha de um pacote que dependa , o que limita severamente a capacidade de outras pessoas de executar meu código. A menos que essa implementação seja perfeita, prefiro escrever minha própria. Alguém tem experiência com esta função?n ( n - 1 ) / 2compositions::MahalanobisDist()
rgl
fonte
Respostas:
Partindo da solução "succint" da ahfoss, usei a decomposição de Cholesky no lugar do SVD.
Deve ser mais rápido, porque a resolução direta de um sistema triangular é mais rápida do que a multiplicação densa de matrizes com a covariância inversa ( veja aqui ). Aqui estão os benchmarks das soluções ahfoss e whuber's em várias configurações:
Então Cholesky parece ser uniformemente mais rápido.
fonte
A fórmula padrão para a distância quadrada de Mahalanobis entre dois pontos de dados é
onde é um vetor p × 1 correspondente à observação i . Normalmente, a matriz de covariância é estimada a partir dos dados observados. Sem contar a inversão da matriz, esta operação requer multiplicações p 2 + p ep 2 + 2 p adições, cada uma repetida n ( n - 1 ) / 2 vezes.xEu p × 1 Eu p2+ p p2+ 2 p n ( n - 1 ) / 2
Considere a seguinte derivação:
onde . Observe quexTiΣ-1qEu= Σ- 12xEu . Isso se baseia no fato de queΣ-1xTEuΣ- 12= ( Σ- 12xEu)T= qTEu é simétrico, o que ocorre devido ao fato de que, para qualquer matriz diagonalizável simétricaA=PEPT,Σ- 12 A = PEPT
Se deixarmos e observar que Σ - 1 é simétrico, veremos que Σ - 1A = Σ- 1 Σ- 1 também deve ser simétrico. SeXé amatrizn×pde observações eQé amatrizn×p, de modo que aithlinha deQéqi, entãoQpode ser expresso sucintamente comoXΣ-1Σ- 12 X n × p Q n × p Eut h Q qEu Q . Este e os resultados anteriores implicam queXΣ- 12
apenas as operações que são computados n ( n - 1 ) / 2 vezes são p multiplicações e 2 p adições (ao contrário das p 2 + p multiplicações e p 2 + 2 p
fonte
pair.diff()
faz e também dar um exemplo numérico com impressões de todas as etapas de sua função? Obrigado.Vamos tentar o óbvio. A partir de
segue, podemos calcular o vetor
no tempo e a matrizO ( p2)
no tempo , provavelmente usando operações de matriz rápidas integradas (paralelizáveis) e, em seguida, forme a solução comoO ( p n2+ p2n )
onde é o produto externo em relação a + : ( a ⊕ b ) i j = a i + b j .⊕ + ( Um ⊕ b )eu j= aEu+ bj.
UmaΣ = Var ( X) h
R
implementação é paralela sucintamente à formulação matemática (e assume, com ela, que é realmente invertível com a escrita inversa h aqui):Observe que, para compatibilidade com as outras soluções, somente os elementos fora da diagonal são retornados, em vez de toda a matriz de distância quadrada (simétrica, zero na diagonal). Os gráficos de dispersão mostram que seus resultados estão de acordo com os de
fastPwMahal
.Em C ou C ++, RAM pode ser re-utilizado e calculado em tempo real, eliminando qualquer necessidade de armazenamento intermediário de u ⊕ u .u ⊕ u u ⊕ u
Temporização estudos com variando de 33 através de 5000 e p variando de 10 para 100 indicam esta aplicação é de 1,5 a 5 vezes mais rápida do que no interior desse intervalo. A melhoria melhora à medida que p e n aumentam. Conseqüentemente, podemos esperar ser superiores para p menores . O ponto de equilíbrio ocorre em torno de p = 7 para n ≥ 100n 33 5000 p 10 100 1.5 5 p n p p = 7 n ≥ 100 . Se as mesmas vantagens computacionais dessa solução direta pertencem a outras implementações pode ser uma questão de quão bem elas tiram vantagem das operações de matriz vetorizada.
fastPwMahal
fastPwMahal
fonte
apply
eouter
... exceto por sairRcpp
.R
parece que não há nada a ganhar com isso.Se você deseja calcular a distância de amostra de Mahalanobis, existem alguns truques algébricos que você pode explorar. Todos eles levam à computação de distâncias euclidianas aos pares, então vamos supor que podemos usarX n × p p O ( n p )
dist()
isso. Deixe denotar a matriz de dados n × p , que supomos estar centralizada para que suas colunas tenham média 0 e ter classificação p para que a matriz de covariância da amostra seja não singular. (A centralização requer operações O ( n p ) .) Então a matriz de covariância da amostra é S = X T X / n .As distâncias de Mahalanobis da amostra em pares de são iguais às distâncias euclidianas de X L em pares para qualquer matriz L que satisfaça L L T = S - 1 , por exemplo, a raiz quadrada ou o fator de Cholesky. Isso decorre de alguma álgebra linear e leva a um algoritmo que requer o cálculo de S , S - 1 e uma decomposição de Cholesky. A pior complexidade é O ( n p 2 + p 3 ) .X
Mais profundamente, estas distâncias referem-se as distâncias entre os componentes principais da amostra de . Deixe X = L D V T denotar o SVD de X . Em seguida, S = V D 2 V T / N e S - 1 / 2 = V D - 1 V T N 1 / 2 . Então X S - 1 / 2 = L V T n 1X X= UD VT X
Aqui está uma implementação R do segundo método que não posso testar no iPad que estou usando para escrever esta resposta.
fonte
Esta é uma solução muito mais sucinta. Ainda é baseado na derivação envolvendo a matriz de covariância de raiz quadrada inversa (veja minha outra resposta a esta pergunta), mas usa apenas a base R e o pacote de estatísticas. Parece ser um pouco mais rápido (cerca de 10% mais rápido em alguns benchmarks que corri). Observe que ele retorna a distância de Mahalanobis, em oposição à distância ao quadrado de Maha.
Essa função requer uma matriz de covariância inversa e não retorna um objeto de distância - mas suspeito que essa versão simplificada da função seja mais útil em geral para empilhar usuários do Exchange.
fonte
SQRT
-o pela decomposição de Choleskychol(invCovMat)
.Se você usar apenas os recursos do Fortran77 na interface, sua sub-rotina ainda será portátil o suficiente para outros.
fonte
Existe uma maneira muito fácil de fazer isso usando o pacote "biotools" do R. Nesse caso, você receberá uma matriz de Mahalanobis de distância ao quadrado.
fonte
Este é o código expandido com minha resposta antiga movida aqui de outro segmento .
Eu venho fazendo há muito tempo o cálculo de uma matriz quadrada simétrica de distâncias pareadas de Mahalanobis no SPSS por meio de uma abordagem de matriz de chapéu usando a solução de um sistema de equações lineares (pois é mais rápido que a inversão da matriz de covariância).
Não sou usuário R, apenas tentei reproduzir esta receita do @ahfoss aqui no SPSS, juntamente com a receita "my", em dados de 1000 casos por 400 variáveis, e achei meu caminho consideravelmente mais rápido.
Portanto, centralize as colunas da matriz de dados, calcule a matriz do chapéu, multiplique por (n-1) e execute a operação oposta à centralização dupla. Você obtém a matriz das distâncias quadradas de Mahalanobis.
Em nossas configurações, a matriz "duplo-concentrado" é especificamente a matriz de chapéu (multiplicada por n-1), não os produtos escalares euclidianos, e a matriz de distância quadrada resultante é, portanto, a matriz de distância quadrada de Mahalanobis, e não a matriz de distância euclidiana quadrada.
H= {H,H,...}
O código no SPSS e na sonda de velocidade está abaixo.
Este primeiro código corresponde à função @ahfoss
fastPwMahal
da resposta citada . É equivalente a isso matematicamente. Mas estou computando a matriz simétrica completa das distâncias (via operações da matriz) enquanto o @ahfoss calculou um triângulo da matriz simétrica (elemento por elemento).A seguir, minha modificação para torná-lo mais rápido:
solve(X'X,X')
fonte
A fórmula que você postou não está computando o que você pensa que está computando (uma estatística U).
No código que eu publiquei, eu uso
cov(x1)
como matriz de escala (esta é a variação das diferenças em pares dos dados). Você está usandocov(x0)
(esta é a matriz de covariância dos seus dados originais). Eu acho que isso é um erro de sua parte. O ponto principal de usar as diferenças aos pares é que você se livra da suposição de que a distribuição multivariada de seus dados é simétrica em torno de um centro de simetria (ou de ter que estimar esse centro de simetria para esse assunto, poiscrossprod(x1)
é proporcional acov(x1)
). Obviamente, ao usar,cov(x0)
você perde isso.Isso está bem explicado no artigo ao qual vinculei minha resposta original.
fonte
Matteo Fasiolo
e (presumo)whuber
neste tópico. O seu é diferente. Eu estaria interessado em entender o que você está calculando, mas é claramente diferente da distância de Mahalanobis, como normalmente definida.cov(x0)
normalmente é usado nesse contexto e parece ser consistente com Croux et. uso de al. O artigo não menciona estatísticas U