您可以使用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而不成功。虽然不知道为什么。



