В зависимости от вашего метрического расстояния c и типа данных, которые вы имеете, у вас есть различные варианты:
Для вашего конкретного c случая, когда данные 1D
и |u-v| == ( (u-v)^2 )^(1/2)
вы можете просто использовать свои знания о том, что верхний и нижний треугольник матрицы расстояний равны в абсолютном выражении и отличаются только по знаку, поэтому вы можете избежать пользовательской функции расстояния:
d = cdist(a, a)
triu_bool = np.triu(np.ones((n_samples, n_samples), dtype=bool))
triu_bool[range(n_samples), range(n_samples)] = False
d[triu_bool] *= -1
# [[ 0. -1. -2.]
# [ 1. 0. -1.]
# [ 2. 1. 0.]]
более общий и, на мой взгляд, лучше подход просто использовать numpys
вещание ( см. также этот вопрос / ответ ). Вот пример для u-v
:
# Generate data
n_dim = 3
n_samples = int(1.5e4)
arr = np.concatenate([np.arange(n_samples)[:, np.newaxis]] * n_dim, axis=-1)
# array([[ 0, 0, 0],
# [ 1, 1, 1],
# [ 2, 2, 2],
# ...,
# [14997, 14997, 14997],
# [14998, 14998, 14998],
# [14999, 14999, 14999]])
# u - v
d = arr[:, np.newaxis, :] - arr[np.newaxis, :, :]
# (n_samples, n_samples, n_dim)
Для симметрии c меры расстояния половина вычислений не нужна. Но по моему опыту это все же быстрее, чем пытаться применить расчет только к верхнему треугольнику или к чему-то подобному.