如何通过重塑 scipy.cdist 的 numpy 数组数组或使用 sklearn 来有效地构建距离矩阵?

How to build efficiently a distance matrix by reshaping numpy array arrays for scipy.cdist or using sklearn?

我正在尝试构建一个包含不同长度数组的距离矩阵。距离度量是适合这种操作的hausdorff距离。尽管如此,我还是找不到使用 scipy.cdist 函数构建距离矩阵的方法。

我在这里寻找 scipy cdist docs and here for hausdorff distance pip install traj-dist and here

现在我可以使用 scipytraj_dist 库获取两个数组之间的距离。

import numpy as np
from scipy.spatial import distance
import traj_dist.distance as tdist
from scipy.spatial.distance import directed_hausdorff
from sklearn.metrics import pairwise_distances
# np.float64 needed for tdist import
arr1 = np.array([10,22,1,22,32,88],
                dtype=np.float64).reshape(3,2)
arr2 = np.array([1,22,32,88,55,11,99,1233],
                dtype=np.float64).reshape(4,2)
# measuring just for 1 array at the time works fine
tdist.hausdorff(array_of_arrays[0],array_of_arrays[1])
directed_hausdorff(array_of_arrays[0],array_of_arrays[1])

我可以用嵌套的 for 循环计算距离矩阵,但是当 n_observation 很大时那会非常慢。

n_observations = array_of_arrays.shape[0]
distance_matrix = np.zeros((n_observations, n_observations))

for i in range(n_observations):
    for j in range(i + 1, n_observations):
        dist = tdist.hausdorff(np.float64(array_of_arrays[i]),
                               np.float64(array_of_arrays[j]),
                               type_d='spherical')
        distance_matrix[i, j] = dist
        distance_matrix[j, i] = dist

但我无法使用 scipy.cdist.

让它在更大范围内工作
array_of_arrays = np.array([arr1, arr2])

distance.cdist(array_of_arrays, array_of_arrays,
               lambda x, y: tdist.hausdorff(x,y))
distance.cdist(array_of_arrays, array_of_arrays,
               lambda x, y: directed_hausdorff(x,y))

sklearn.metrics.pairwise_distance也不行


pairwise_distances(array_of_arrays, metric=tdist.hausdorff)

问题是:如何重塑array_of_arrays以在其上使用scipy.cdist

奖金子问题:如果scipy.cdist不适合这样的任务,我应该用什么来避免嵌套的for循环并计算一个distance_matrix?

据我所知,问题在于定向 Hausdorff 距离是在维度为 (N,D) 和 (M,D) 的两个数组之间计算的,并且没有为 one-dimensional 数组定义(即向量)。 cdist 仅将二维数组作为输入,这意味着这些张量的每一行都被视为一个单独的观察值。要使用 SciPy 的 cdist 解决此问题,您需要能够将 3D 张量传递给 cdist,这在设计上是不允许的(它会检查张量的维数)。

一种可能的解决方法(这并不容易)是获取用 Cython (https://github.com/scipy/scipy/blob/v1.5.2/scipy/spatial/_hausdorff.pyx) 编写的定向 Hausdorff 距离的源代码并尝试对其进行矢量化。