如何通过重塑 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 。
现在我可以使用 scipy
或 traj_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 距离的源代码并尝试对其进行矢量化。
我正在尝试构建一个包含不同长度数组的距离矩阵。距离度量是适合这种操作的hausdorff距离。尽管如此,我还是找不到使用 scipy.cdist
函数构建距离矩阵的方法。
我在这里寻找 scipy cdist docs and here for hausdorff distance pip install traj-dist
and here
现在我可以使用 scipy
或 traj_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 距离的源代码并尝试对其进行矢量化。