numpy python: векторизованная функция расстояния для вычисления попарного расстояния матрицы 2 с размером (м, 3) - PullRequest
2 голосов
/ 03 февраля 2020

У меня есть два numpy массива A и B. Форма A - (м, 3), а форма B - (n, 3).

Эти матрицы выглядят так:

A
#output
array([[  9.227,  -4.698, -95.607],
   [ 10.294,  -4.659, -94.606],
   [ 11.184,  -5.906, -94.675],
   ...,
   [ 19.538, -91.572, -45.361],
   [ 20.001, -92.655, -45.009],
   [ 19.271, -92.726, -45.79 ]])

Таким образом, он содержит для каждой строки координаты x, y, z трехмерной точки. B следует тому же формату.

У меня есть эта функция (np равно numpy):

def compute_dist(point1, point2):
    squared = (point1-point2)**2
    return (np.sqrt(np.sum(squares)))

Я хочу вычислить попарно расстояние между A и B, используя векторизованную функцию.

Я пытаюсь это сделать:

 v = np.vectorize(compute_dist)
 v(A, B)
 #output
 matrix([[37.442, 42.693, 72.705],
    [37.442, 42.693, 72.705],
    [37.442, 42.693, 72.705],
    ...,
    [37.442, 42.693, 72.705],
    [37.442, 42.693, 72.705],
    [37.442, 42.693, 72.705]])

Я не понимаю, как использовать векторизацию, даже если я прочитал do c. Как я могу вычислить матрицу, которая содержит попарно расстояние между A и B? Я знаю, что есть scipy.distance.cdist , но я хочу сделать это сам с np.vectorize .

Меня не волнует формат вывода (список, массив, матрица ...). В конце я просто хочу найти минимальное расстояние.

1 Ответ

4 голосов
/ 03 февраля 2020

Вы можете использовать np.newaxis до развернуть размеры двух ваших массивов A и B, чтобы включить вещание, а затем выполнить свои вычисления.

Попарное расстояние означает каждую точку в A (m, 3) следует сравнивать с каждой точкой в ​​B (n, 3). Это приводит к матрице расстояний (m, n). С numpy можно использовать трансляцию для достижения желаемого результата. При использовании A=A[:, np.newaxis, :] и B=B[np.newaxis, :, :] получаются формы A (m, 1, 3) и B(1, n, 3) соответственно. Если вы затем выполните расчет, такой как C = A-B numpy, автоматически транслируется. Это означает, что вы получаете копию всех m строк A для всех n столбцов B и копию всех n столбцов B для всех m строк A.

  A (m, 1, 3)
- B (1, n, 3)
--------------
= C (m, n, 3)

Чтобы получить матрицу расстояний, вы можете чем использовать numpy.linalg.norm():

import numpy as np
m = 10
n = 12
A = np.random.random((m, 3))
B = np.random.random((n, 3))

# Add newaxis on seconbd axis of A and on first axis on B
# shape: (m, n, 3) = (m, 1, 3) - (1, n, 3)
C = A[:, np.newaxis, :] - B[np.newaxis, :, :]

C = np.linalg.norm(C, axis=-1)
# shape: (m, n)
...