Это, наверное, самый частый вопрос (я сам дважды отвечал на него за последнюю неделю), но, поскольку его можно сформулировать миллионами способов:
import numpy as np
import scipy.spatial.distance.cdist as cdist
def withScipy(X,Y): # faster
return np.argmin(cdist(X,Y,'sqeuclidean'),axis=0)
def withoutScipy(X,Y): #slower, using broadcasting
return np.argmin(np.sum((X[None,:,:]-Y[:,None,:])**2,axis=-1), axis=0)
Также существует метод только с numpy, использующий einsum
, который быстрее, чем моя функция (но не cdist
), но я не понимаю ее достаточно хорошо, чтобы это объяснить.
EDIT + = 21 месяц:
Однако лучший способ сделать это алгоритмически - использовать KDTree.
from sklearn.neighbors import KDTree
# since the sklearn implementation allows return_distance = False, saving memory
y_tree = KDTree(Y)
y_index_of_closest = y_tree.query(X, k = 1, return_distance = False)
@HansMusgrave имеет довольно хорошее ускорение для KDTree ниже.
И для завершения, ответ np.einsum
, который я теперь понимаю:
np.argmin( # (X - Y) ** 2
np.einsum('ij, ij ->i', X, X)[:, None] + # = X ** 2 \
np.einsum('ij, ij ->i', Y, Y) - # + Y ** 2 \
2 * X.dot(Y.T), # - 2 * X * Y
axis = 1)
@Divakar хорошо объясняет этот метод на странице вики своего пакет eucl_dist
person
Daniel F
schedule
12.12.2016