python中是否有类似于scipy.spatial.distance.cdist的东西,但用于位移(fast)?

python中是否有类似于scipy.spatial.distance.cdist的东西,但用于位移(fast)?,python,numpy,scipy,scipy-spatial,Python,Numpy,Scipy,Scipy Spatial,几周来,我一直在研究一个代码,并一直试图通过使用cdist而不是多级for循环来计算矩阵中每个点之间的距离来加速它 我想要的是: from scipy.spatial.distance import cdist import numpy as np a=np.array([[1],[2],[3]]) cdist(a,a, lambda u,v: u-v) 然而,我的问题是,在我的研究背景下,a相当大,在cdist中使用自定义lambda函数要比cdist(a,

几周来,我一直在研究一个代码,并一直试图通过使用cdist而不是多级for循环来计算矩阵中每个点之间的距离来加速它

我想要的是:

    from scipy.spatial.distance import cdist
    import numpy as np

    a=np.array([[1],[2],[3]])
    cdist(a,a, lambda u,v: u-v)
然而,我的问题是,在我的研究背景下,a相当大,在cdist中使用自定义lambda函数要比cdist(a,a)慢很多(~2个数量级),但这只能给出正值。i、 实际上,我必须计算15000次,其中a有1000个元素,所以这些元素非常重要

注:cdist(a,a)没有给出所需的输出,因为它都是正值

[[0. 1. 2.]
 [1. 0. 1.]
 [2. 1. 0.]]
我希望你们能给我一些建议,告诉我如何从cdist创建所需的有符号输出,但要比使用lambda函数更快


谢谢大家!

根据您的距离度量和数据类型,您有不同的选择:

对于您的特定情况,如果数据是
1D
u-v |=((u-v)^2)^(1/2)
,您可以利用您的知识,即距离矩阵的上下三角形在绝对值上相等,并且仅在符号方面不同,因此可以避免使用自定义距离函数:

d = cdist(a, a)

triu_bool = np.triu(np.ones((n_samples, n_samples), dtype=bool))
triu_bool[range(n_samples), range(n_samples)] = False
d[triu_bool] *= -1
# [[ 0. -1. -2.]
#  [ 1.  0. -1.]
#  [ 2.  1.  0.]]
在我看来,更普遍、更好的方法是简单地使用
numpys
broadcasting()。 下面是一个u-v
u-v
的示例:

# Generate data
n_dim = 3
n_samples = int(1.5e4)
arr = np.concatenate([np.arange(n_samples)[:, np.newaxis]] * n_dim, axis=-1)
# array([[    0,     0,     0],
#        [    1,     1,     1],
#        [    2,     2,     2],
#        ...,
#        [14997, 14997, 14997],
#        [14998, 14998, 14998],
#        [14999, 14999, 14999]])

# u - v
d = arr[:, np.newaxis, :] - arr[np.newaxis, :, :]
# (n_samples, n_samples, n_dim)

对于对称距离测量,一半的计算是不必要的。但根据我的经验,这仍然比仅将计算应用于上三角形或类似对象要快。

根据您的距离度量和数据类型,您有不同的选择:

对于您的特定情况,如果数据是
1D
u-v |=((u-v)^2)^(1/2)
,您可以利用您的知识,即距离矩阵的上下三角形在绝对值上相等,并且仅在符号方面不同,因此可以避免使用自定义距离函数:

d = cdist(a, a)

triu_bool = np.triu(np.ones((n_samples, n_samples), dtype=bool))
triu_bool[range(n_samples), range(n_samples)] = False
d[triu_bool] *= -1
# [[ 0. -1. -2.]
#  [ 1.  0. -1.]
#  [ 2.  1.  0.]]
在我看来,更普遍、更好的方法是简单地使用
numpys
broadcasting()。 下面是一个u-v
u-v
的示例:

# Generate data
n_dim = 3
n_samples = int(1.5e4)
arr = np.concatenate([np.arange(n_samples)[:, np.newaxis]] * n_dim, axis=-1)
# array([[    0,     0,     0],
#        [    1,     1,     1],
#        [    2,     2,     2],
#        ...,
#        [14997, 14997, 14997],
#        [14998, 14998, 14998],
#        [14999, 14999, 14999]])

# u - v
d = arr[:, np.newaxis, :] - arr[np.newaxis, :, :]
# (n_samples, n_samples, n_dim)

对于对称距离测量,一半的计算是不必要的。但根据我的经验,这比只对上三角形或类似的东西进行计算要快。

这解决了我的问题,我把它标记为已经这样做了。非常感谢。这解决了我的问题——我把它标记为已经这样做了。非常感谢。