Самый быстрый способ вычислить угол между 2D векторами - PullRequest
2 голосов
/ 17 июня 2019

Я ищу эффективные альтернативные способы вычисления угла косинуса между 2D векторами. Ваше понимание этой проблемы очень поможет.

Постановка проблемы:

vectors - это двумерный массив, в котором хранятся векторы. Форма массива vectors равна (N, 2), где N - количество векторов. vectors[:, 0] имеет x-компонент, а vectors[:, 1] имеет y-компонент.

Я должен найти угол между всеми векторами в vectors. Например, если в vectors есть три вектора A, B, C, мне нужно найти угол между A and B, B and C и A and C.

Я реализовал это и хочу узнать альтернативные способы.

Текущая реализация:

vectors = np.array([[1, 3], [2, 4], [3, 5]])

vec_x = vectors[:, 0]
vec_y = vectors[:, 1]

a1 = np.ones([vec_x.shape[0], vec_x.shape[0]]) * vec_x
a2 = np.ones([vec_x.shape[0], vec_x.shape[0]]) * vec_y
a1b1 = a1 * a1.T
a2b2 = a2 * a2.T
mask = np.triu_indices(a1b1.shape[0], 0) # We are interested in lower triangular matrix
a1b1[mask] = 0
a2b2[mask] = 0
numer = a1b1 + a2b2
denom = np.ones([vec_x.shape[0], vec_x.shape[0]]) * np.sqrt(np.square(a1) + np.square(a2))
denom = denom * denom.T
denom[mask] = 0
eps = 1e-7
dot_res = np.rad2deg(np.arccos(np.divide(numer, denom + eps)))
dot_res[mask] = 0
print(dot_res)

Вывод:

[[ 0.          0.          0.        ]
 [ 8.13010519  0.          0.        ]
 [12.52880911  4.39870821  0.        ]]

Вопросы:

  1. Есть ли альтернативный способ сделать это более эффективным?

  2. Можем ли мы каким-то образом улучшить скорость текущей версии?

1 Ответ

2 голосов
/ 17 июня 2019

Использование scipy.spatial.distance.pdist:

import numpy as np
import scipy.spatial.distance

vectors = np.array([[1, 3], [2, 4], [3, 5]])
# Compute cosine distance
dist = scipy.spatial.distance.pdist(vectors, 'cosine')
# Compute angles
angle = np.rad2deg(np.arccos(1 - dist))
# Make it into a matrix
angle_matrix = scipy.spatial.distance.squareform(angle)
print(angle_matrix)
# [[ 0.          8.13010235 12.52880771]
#  [ 8.13010235  0.          4.39870535]
#  [12.52880771  4.39870535  0.        ]]
...