/ / ¿Una forma eficiente de construir una matriz de distancias por pares entre muchos vectores? - Python, Numpy, Scipy, memoria eficiente, escalable

¿Una forma eficiente de construir una matriz de distancias por pares entre muchos vectores? - Python, Numpy, Scipy, memoria eficiente, escalable

Primero, gracias por leer y tomarse el tiempo para responder.

En segundo lugar, la pregunta:

Tengo una matriz PxN X donde P está en el orden de10 ^ 6 y N es del orden de 10 ^ 3. Entonces, X es relativamente grande y no es escaso. Digamos que cada fila de X es una muestra de N dimensiones. Quiero construir una matriz PxP de distancias en pares entre estas muestras de P. Digamos también que estoy interesado en las distancias de Hellinger.

Hasta ahora estoy confiando en matrices dok dispersas:

def hellinger_distance(X):
P = X.shape[0]
H1 = sp.sparse.dok_matrix((P, P))
for i in xrange(P):
if i%100 == 0:
print i
x1 = X[i]
X2 = X[i:P]
h = np.sqrt(((np.sqrt(x1) - np.sqrt(X2))**2).sum(1)) / math.sqrt(2)
H1[i, i:P] = h
H = H1 + H1.T
return H

Esto es super lento. ¿Hay una manera más eficiente de hacer esto? Cualquier ayuda es muy apreciada.

Respuestas

2 para la respuesta № 1

Puedes usar pdist y squareform de scipy.spatial.distance -

from scipy.spatial.distance import pdist, squareform

out = squareform(pdist(np.sqrt(X)))/np.sqrt(2)

O usar cdist de lo mismo

from scipy.spatial.distance import cdist

sX = np.sqrt(X)
out = cdist(sX,sX)/np.sqrt(2)

1 para la respuesta № 2

Además de la respuesta de Divakar, me di cuenta de que hay una implementación de esto en sklearn que permite el procesamiento paralelo:

from sklearn.metrics.pairwise import pairwise_distances
njobs = 3
H = pairwise_distances(np.sqrt(X), n_jobs=njobs, metric="euclidean") / math.sqrt(2)

Haré una evaluación comparativa y publicaré los resultados más tarde.