Я ищу эффективный способ ( нет для петель ) для вычисления евклидова расстояния между набором выборок и набором центроидов кластеров.
Пример:
import numpy as np
X = np.array([[1,2,3],[1, 1, 1],[0, 2, 0]])
y = np.array([[1,2,3], [0, 1, 0]])
Ожидаемый результат:
array([[ 0., 11.],
[ 5., 2.],
[10., 1.]])
Это квадрат евклидова расстояния между каждым образцом в X и каждым центроидом в y.
Я придумал 2 решения:
Решение 1:
def dist_2(X,y):
X_square_sum = np.sum(np.square(X), axis = 1)
y_square_sum = np.sum(np.square(y), axis = 1)
dot_xy = np.dot(X, y.T)
X_square_sum_tile = np.tile(X_square_sum.reshape(-1, 1), (1, y.shape[0]))
y_square_sum_tile = np.tile(y_square_sum.reshape(1, -1), (X.shape[0], 1))
dist = X_square_sum_tile + y_square_sum_tile - (2 * dot_xy)
return dist
dist = dist_2(X, y)
решение 2:
import scipy
dist = scipy.spatial.distance.cdist(X,y)**2
Производительность (настенное время) решения «два»
import time
X = np.random.random((100000, 50))
y = np.random.random((100, 50))
start = time.time()
dist = scipy.spatial.distance.cdist(X,y)**2
end = time.time()
print (end - start)
Среднее время нахождения настенных часов = 0,7 с
start = time.time()
dist = dist_2(X,y)
end = time.time()
print (end - start)
Среднее время нахождения настенных часов = 0,3 с
Тест на большое количество центроидов
X = np.random.random((100000, 50))
y = np.random.random((1000, 50))
Среднее время нахождения настенных часов в «решении 1» = 50 с (+ проблема с памятью)
Среднее время нахождения настенных часов в «решении 2» = 6 секунд !!!
Заключение
Похоже, что "решение 1 более эффективно, чем" решение 2 "в отношении среднего истекшего времени настенных часов (для небольших наборов данных), но неэффективно в отношении памяти.
Есть предложения?