Расчет манхэттенское расстояние используя Numpy

Подскажите, как можно модифицировать код, для расчета манхэттенского расстояния, что бы избавиться от цикла то есть использовать для расчета только библиотеку Numpy.

import numpy as np

train = np.random.randint(0, 255, (1000, 10))
test = np.random.randint(0, 255, (100, 10))

num_train = train.shape[0]
num_test = test.shape[0]

dists = np.zeros((num_test, num_train), np.float32)
for i_test in range(num_test):
    dists[i_test] = np.linalg.norm(test[i_test] - train, ord=1, axis=1)

Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

То что вам нужно - вычислить декартово произведение train и test, получить разности в виде векторов, перевести разницы в расстояния. Небольшое демо:

train = np.array([[1, 1], [2, 2], [3, 3]])
test  = np.array([[1, 1], [2, 2]])

# train = [[1 1] [2 2] [3 3]]
# test = [[1 1] [2 2]]

a = np.repeat(train[np.newaxis, :, :], test.shape[0], axis=0)
# каждая строка нового массива - копия train
# a = [
#     [[1 1] [2 2] [3 3]]
#     [[1 1] [2 2] [3 3]]
# ]

b = np.repeat(test[:, np.newaxis, :], train.shape[0], axis=1)
# каждый столбец нового массива - копия test
# b = [
#     [[1 1] [1 1] [1 1]]
#     [[2 2] [2 2] [2 2]]
# ]

c = a - b
# попарные разницы векторов из train и test
# c = [
#     [[ 0  0] [ 1  1] [ 2  2]]
#     [[-1 -1] [ 0  0] [ 1  1]]
# ]

dists = np.linalg.norm(с, axis=2, ord=1)
# заменяем разницы на манхэтенновские нормы
# dists = [
#     [0. 2. 4.]
#     [2. 0. 2.]
# ]

Рабочий пример:

import numpy as np

train = np.random.randint(0, 255, (1000, 10))
test  = np.random.randint(0, 255, (100, 10))

a = np.repeat(train[np.newaxis, :         , :], test .shape[0], axis=0)
b = np.repeat(test [:         , np.newaxis, :], train.shape[0], axis=1)

dists = np.linalg.norm(a - b, axis=2, ord=1)

print(dists.shape)
print(dists)
→ Ссылка