python - x 两行点之间的距离

标签 python numpy scipy

我有两个一维 numpy 数组 A 和 B,大小分别为 (n, ) 和 (m, ),它们对应于直线上点的 x 位置。我想计算 A 中每个点到 B 中每个点之间的距离。然后我需要使用这些距离设置的 y 距离 d,来计算 A 中每个点的电势。

我目前使用的是:

V = numpy.zeros(n)
for i in range(n):
    xdist = A[i] - B
    r = numpy.sqrt(xdist**2 + d**2)
    dV = 1/r
    V[i] = numpy.sum(dV)

这可行,但对于大型数据集可能需要一段时间,所以我想使用类似于 scipy.spatial.distance.cdist 的函数,它不适用于一维数组,我不想添加另一个维度到阵列,因为它们变得太大。

最佳答案

矢量化方法

A 扩展到 2D 并使用 np.newaxis/None 引入新轴后的一种矢量化方法从而利用broadcasting会是——

(1/(np.sqrt((A[:,None] - B)**2 + d**2))).sum(1)

大型阵列的混合方法

现在,对于大型数组,我们可能必须将数据分成 block 。

因此,使用 BSZ 作为 block 大小,我们将采用混合方法,就像这样 -

dsq = d**2   
V = np.zeros((n//BSZ,BSZ))
for i in range(n//BSZ):
    V[i] = (1/(np.sqrt((A[i*BSZ:(i+1)*BSZ,None] - B)**2 + dsq))).sum(1)

运行时测试

方法-

def original_app(A,B,d):
    V = np.zeros(n)
    for i in range(n):
        xdist = A[i] - B
        r = np.sqrt(xdist**2 + d**2)
        dV = 1/r
        V[i] = np.sum(dV)
    return V

def vectorized_app1(A,B,d):
    return (1/(np.sqrt((A[:,None] - B)**2 + d**2))).sum(1)
    
def vectorized_app2(A,B,d, BSZ = 100):
    dsq = d**2   
    V = np.zeros((n//BSZ,BSZ))
    for i in range(n//BSZ):
        V[i] = (1/(np.sqrt((A[i*BSZ:(i+1)*BSZ,None] - B)**2 + dsq))).sum(1)
    return V.ravel()

时间和验证-

In [203]: # Setup inputs
     ...: n,m = 10000,2000
     ...: A = np.random.rand(n)
     ...: B = np.random.rand(m)
     ...: d = 10
     ...: 

In [204]: out1 = original_app(A,B,d)
     ...: out2 = vectorized_app1(A,B,d)
     ...: out3 = vectorized_app2(A,B,d, BSZ = 100)
     ...: 
     ...: print np.allclose(out1, out2)
     ...: print np.allclose(out1, out3)
     ...: 
True
True

In [205]: %timeit original_app(A,B,d)
10 loops, best of 3: 133 ms per loop

In [206]: %timeit vectorized_app1(A,B,d)
10 loops, best of 3: 138 ms per loop

In [207]: %timeit vectorized_app2(A,B,d, BSZ = 100)
10 loops, best of 3: 65.2 ms per loop

我们可以使用参数 block 大小 BSZ -

In [208]: %timeit vectorized_app2(A,B,d, BSZ = 200)
10 loops, best of 3: 74.5 ms per loop

In [209]: %timeit vectorized_app2(A,B,d, BSZ = 50)
10 loops, best of 3: 67.4 ms per loop

因此,在我这边,最好的方法似乎是在 block 大小为 100 的情况下提供 2x 加速。

关于python - x 两行点之间的距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42281960/

相关文章:

python - NumPy 中与 NaN 相关的矩阵

python - matplotlib pyplot.plot() : How do you plot data as a line when the data contains a single value surrounded by masks?

python - 是否有 scipy/numpy 方法来获取最近插值的索引?

python - 获得最大相干面积

python - lambda 类型与 defaultdict 一起使用时到底有什么作用

python - 使用 Python 在文件之间插入一些行

Python SimpleHTTPServer 不断下降,我不知道为什么

python - 如何正确地向装饰器添加类型提示?

python - 在 pandas 数据框(和)列表上使用 scipy pdist

Python:插值的集成