gpt4 book ai didi

Python,Pairwise 'distance',需要一种快速的方法来完成

转载 作者:太空狗 更新时间:2023-10-29 21:39:42 24 4
gpt4 key购买 nike

在我博士期间的一个副业项目中,我参与了用 Python 对一些系统进行建模的任务。在效率方面,我的程序在以下问题中遇到了瓶颈,我将在一个最小工作示例中公开该问题。

我处理大量由 3D 起点和终点编码的片段,因此每个片段由 6 个标量表示。

我需要计算成对的最小段间距离。两个段之间的最小距离的解析表达式在这个 source 中找到.致 MWE:

import numpy as np
N_segments = 1000
List_of_segments = np.random.rand(N_segments, 6)

Pairwise_minimal_distance_matrix = np.zeros( (N_segments,N_segments) )
for i in range(N_segments):
for j in range(i+1,N_segments):

p0 = List_of_segments[i,0:3] #beginning point of segment i
p1 = List_of_segments[i,3:6] #end point of segment i
q0 = List_of_segments[j,0:3] #beginning point of segment j
q1 = List_of_segments[j,3:6] #end point of segment j
#for readability, some definitions
a = np.dot( p1-p0, p1-p0)
b = np.dot( p1-p0, q1-q0)
c = np.dot( q1-q0, q1-q0)
d = np.dot( p1-p0, p0-q0)
e = np.dot( q1-q0, p0-q0)
s = (b*e-c*d)/(a*c-b*b)
t = (a*e-b*d)/(a*c-b*b)
#the minimal distance between segment i and j
Pairwise_minimal_distance_matrix[i,j] = sqrt(sum( (p0+(p1-p0)*s-(q0+(q1-q0)*t))**2)) #minimal distance

现在,我意识到这是极其低效的,这就是我来这里的原因。我已经广泛研究了如何避免循环,但遇到了一些问题。显然,这种计算最好用 cdist 完成。 python 。但是,它可以处理的自定义距离函数必须是二元函数。这在我的例子中是个问题,因为我的向量的长度特别是 6,并且必须按位拆分成它们的前 3 个分量和后 3 个分量。我不认为我可以将距离计算转化为二元函数。

欢迎任何意见。

最佳答案

您可以使用 numpy 的向量化功能来加速计算。我的版本一次计算距离矩阵的所有元素,然后将对角线和下三角设置为零。

def pairwise_distance2(s):
# we need this because we're gonna divide by zero
old_settings = np.seterr(all="ignore")

N = N_segments # just shorter, could also use len(s)

# we repeat p0 and p1 along all columns
p0 = np.repeat(s[:,0:3].reshape((N, 1, 3)), N, axis=1)
p1 = np.repeat(s[:,3:6].reshape((N, 1, 3)), N, axis=1)
# and q0, q1 along all rows
q0 = np.repeat(s[:,0:3].reshape((1, N, 3)), N, axis=0)
q1 = np.repeat(s[:,3:6].reshape((1, N, 3)), N, axis=0)

# element-wise dot product over the last dimension,
# while keeping the number of dimensions at 3
# (so we can use them together with the p* and q*)
a = np.sum((p1 - p0) * (p1 - p0), axis=-1).reshape((N, N, 1))
b = np.sum((p1 - p0) * (q1 - q0), axis=-1).reshape((N, N, 1))
c = np.sum((q1 - q0) * (q1 - q0), axis=-1).reshape((N, N, 1))
d = np.sum((p1 - p0) * (p0 - q0), axis=-1).reshape((N, N, 1))
e = np.sum((q1 - q0) * (p0 - q0), axis=-1).reshape((N, N, 1))

# same as above
s = (b*e-c*d)/(a*c-b*b)
t = (a*e-b*d)/(a*c-b*b)

# almost same as above
pairwise = np.sqrt(np.sum( (p0 + (p1 - p0) * s - ( q0 + (q1 - q0) * t))**2, axis=-1))

# turn the error reporting back on
np.seterr(**old_settings)

# set everything at or below the diagonal to 0
pairwise[np.tril_indices(N)] = 0.0

return pairwise

现在让我们试一试。在你的例子中,N = 1000,我得到了一个时间

%timeit pairwise_distance(List_of_segments)
1 loops, best of 3: 10.5 s per loop

%timeit pairwise_distance2(List_of_segments)
1 loops, best of 3: 398 ms per loop

当然,结果是一样的:

(pairwise_distance2(List_of_segments) == pairwise_distance(List_of_segments)).all()

返回 True。我也很确定算法中某处隐藏了一个矩阵乘法,因此应该有进一步加速(以及清理)的潜力。

顺便说一句:我试过先简单地使用 numba 但没有成功。不过不知道为什么。

关于Python,Pairwise 'distance',需要一种快速的方法来完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28693494/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com