Самый быстрый способ рассчитать евклидово расстояние между двумя наборами векторов с помощью numpy или scipy

Хорошо, я недавно обнаружил, что команда scipy.spatial.distance.cdist очень быстро решает ПОЛНУЮ матрицу расстояний между двумя векторными массивами для источника и назначения. см .: Как можно вычислить евклидово расстояние с помощью numpy? Я хотел попытаться продублировать этот выигрыш в производительности достигается при решении расстояния между двумя массивами одинакового размера. Расстояние между двумя ОДНИМИ векторами довольно просто вычислить, как показано в предыдущей ссылке. Мы можем взять векторы:

    import numpy as np
    A=np.random.normal(size=(3))
    B=np.random.normal(size=(3))

а затем используйте ´numpy.linalg.norm´, где

    np.linalg.norm(A-B)

эквивалентно

    temp = A-B
    np.sqrt(temp[0]**2+temp[1]**2+temp[2]**2)

что хорошо работает, однако, когда я хочу знать расстояние между двумя наборами векторов, где my_distance = distance_between( A[i], B[i] ) for all i второе решение работает отлично. В этом, как и ожидалось:

    A=np.random.normal(size=(3,42))
    B=np.random.normal(size=(3,42))     
    temp = A-B
    np.sqrt(temp[0]**2+temp[1]**2+temp[2]**2)

дает мне набор из 42 расстояний между i -м элементом A и i -м элементом B. В то время как функция norm правильно вычисляет норму для всей матрицы, давая мне одно значение, которое я не ищу. Я хочу сохранить поведение с 42 расстояниями, надеюсь, с почти такой же скоростью, как я получаю от cdist для решения полных матриц. Итак, вопрос в том, как наиболее эффективно использовать python и numpy / scipy для вычисления i расстояний между данными с формой (n,i)?

Спасибо, Слоан


person SoulNibbler    schedule 10.12.2012    source источник


Ответы (2)


Думаю, вы уже сами раскрыли большую часть дела. Однако вместо вашей последней строки я бы использовал:

np.sqrt(np.sum(temp**2,0))
person Rolf Bartstra    schedule 10.12.2012
comment
Спасибо, я опишу это и посмотрю, какой выигрыш мне принесет. Я действительно надеялся, что есть способ использовать одну из библиотек C для повышения производительности. - person SoulNibbler; 12.12.2012
comment
Как ни странно, на самом деле в 3 раза быстрее использовать np.sqrt(temp[0]**2+temp[1]**2+temp[2]**2) для 1 миллиона элементов. - person SoulNibbler; 12.12.2012
comment
Это действительно неожиданный (и тревожный) результат ...! Змея действует загадочным образом ... ;-). Мне очень интересно, почему это так, так что вы хотите задать новый вопрос по этому поводу, или я должен? - person Rolf Bartstra; 13.12.2012
comment
Я позволю вам опубликовать его, но я могу поделиться кодом своего профиля по вопросу. - person SoulNibbler; 14.12.2012
comment
@SoulNibbler К вашему сведению, я разместил новый вопрос по проблеме скорости, см. stackoverflow.com/questions/14566564/ - person Rolf Bartstra; 28.01.2013

Вот сравнение по времени для двух методов, которые я считаю наиболее подходящими:

import timeit
In[19]:    timeit.timeit(stmt='np.linalg.norm(x-y,axis=0)', setup='import numpy as np; x,y = np.random.normal(size=(10, 100)), np.random.normal(size=(10, 100))', number=1000000)
Out[19]:   15.132534857024439

In[20]:    timeit.timeit(stmt='np.sqrt(np.sum((x-y),axis=1))', setup='import numpy as np; x,y = np.random.normal(size=(10, 100)), np.random.normal(size=(10, 100))', number=1000000)
Out[20]:   9.417887529009022

Я не удивлен, что метод numpy работает быстрее. Я считаю, что по мере совершенствования Python многие из этих встроенных функций будут улучшены.

Тесты проводились на anaconda python версии 3.5.2.

person foladev    schedule 03.04.2017