Plus rapide par paires distance métrique en python
J'ai un 1D tableau de nombres, et que vous voulez calculer toutes les distances euclidiennes. J'ai une méthode de (grâce à) de le faire avec de la radiodiffusion, mais il est inefficace parce qu'il calcule la distance deux fois. Et il n'est pas à l'échelle.
Voici un exemple qui me donne ce que je veux avec un tableau de 1000 numéros.
import numpy as np
import random
r = np.array([random.randrange(1, 1000) for _ in range(0, 1000)])
dists = np.abs(r - r[:, None])
Quelle est la manière la plus rapide de mise en œuvre dans scipy/numpy/scikit-learn que je peux utiliser, pour ce faire, étant donné qu'elle a pour s'adapter à des situations où les 1D tableau a >10k valeurs.
Remarque: la matrice est symétrique, donc je suppose qu'il est possible d'obtenir au moins un 2x speedup par l'aborder, je ne sais juste pas comment.
scipy.spatial.distance.pdist
. Je ne sais pas si c'est l'option la plus rapide, car il a besoin d'avoir des contrôles pour les données multidimensionnelles, non-Euclidienne normes, et d'autres choses, mais il est intégré.Combien de temps il vous faut pour cela être? Il ne va jamais à l'échelle de mieux que O(n^2), puisque vous avez à remplir n^2 entrées de sortie. Votre solution existante est O(n^2), et il ne semble pas beaucoup de place pour les principales optimisations.
Cela semble échelle >10k valeurs assez bien déjà quand je l'ai essayer. N'oubliez pas que vous devez remplir à 100 millions d'entrées de sortie. C'est presque la moitié d'un gigaoctet de paires distances.
Je ne le pense pas... Si vous suivez le code source, à la fin, ceci est la fonction qui est appelé. Non seulement il n'y a pas de fantaisie, d'optimisation, mais pour 1D vecteurs c'est la quadrature et en prenant la racine carrée de calculer la valeur absolue. Probablement pire que l'OP du code pour son cas d'utilisation particulier.
Si je ne me trompe pas,
scipy
est toujours compilé avec BLAS, c'est pas une option comme avec numpy
.
OriginalL'auteur roblanf | 2013-11-29
Vous devez vous connecter pour publier un commentaire.
Ni l'un ni l'autre des réponses tout à fait répondu à la question 1 a été en Cython, on a été plus lent. Mais à la fois très utiles conseils. Leur mise en place suggère que
scipy.spatial.distance.pdist
est le chemin à parcourir.Voici un code:
De la synchronisation avec IPython:
Je n'ai pas essayé la Cython de mise en œuvre (je ne peux pas l'utiliser pour ce projet), mais comparer mes résultats à l'autre réponse qui l'a fait, il ressemble à
scipy.spatial.distance.pdist
est environ un tiers plus lent que le Cython de mise en œuvre (en prenant en compte les différentes machines par l'analyse comparative sur la np.abs solution).OriginalL'auteur roblanf
Ici est un Cython de mise en œuvre qui donne plus de 3X amélioration de la vitesse pour cet exemple sur mon ordinateur. Ce calendrier doit être examiné pour les grands tableaux difficile, parce que les routines BLAS pouvez probablement échelle beaucoup mieux que cela, plutôt naïf code.
Je sais que vous avez demandé quelque chose à l'intérieur de scipy/numpy/scikit-learn, mais peut-être cela va ouvrir de nouvelles possibilités pour vous:
Fichier
my_cython.pyx
:La réponse est un 1-D tableau contenant tous les non-répétée évaluations.
À l'importation dans Python:
De la synchronisation avec IPython:
fabs
--abs
estint
variante.OriginalL'auteur Saullo G. P. Castro
À l'aide de la moitié de la mémoire, mais 6 fois plus lent que
np.abs(r - r[:, None])
:OriginalL'auteur cyborg