计算 numpy 行间叉积的欧几里德距离?

BBQ*_*cus 4 python arrays numpy

我有两个带有坐标数的 numpy 数组n(每行两个项目)。

coords_a = np.random.random((20, 2))
coords_b = np.random.random((20, 2))
Run Code Online (Sandbox Code Playgroud)

现在,对于每个行组合,我想计算一个函数并将返回值保存为矩阵中的项目。因此,生成的数组应该具有形状(20, 20)并且可以“延迟”计算,如下所示。作为示例性函数,使用欧几里德距离。

def euclidean_dist(x1: float, y1: float, x2: float, y2: float) -> float:
    """Return the euclidean distance between two the points (x1, y1) and (x2, y2)."""
    return np.sqrt(np.square(x1 - x2) + np.square(y1 - y2))

matrix = []
for a in coords_a:
    row = []
    for b in coords_b:
        row.append(euclidean_dist(*a, *b))
    matrix.append(row)
    
matrix = np.array(matrix)
Run Code Online (Sandbox Code Playgroud)

正如您可以想象的那样,这个嵌套的 for 循环非常耗时,仅处理 2000 个坐标对就花费了 25 秒以上。是否有推荐的方法来向量化这种叉积?

提前致谢。

FBr*_*esi 5

我想补充我的 2 美分,因为并非每个函数都已在 numpy 或 scipy 中实现。一般来说,您可以使用numpy 广播来实现矢量化解决方案。\n对于欧几里德距离的具体情况,您可以这样做:

\n
import numpy as np\n\n# Define the arrays of coordinates\ncoords_a = np.random.random((20, 2))\ncoords_b = np.random.random((20, 2))\n\n# Expand their dimensions\na = coords_a[:, None]\nb = coords_b[None, None]\n\n# Use broadcasting to compute pairwise difference\nd = a-b\n\n# Apply formula for euclidean distance\nr = np.sqrt(np.sum(d**2, axis=-1)) \n
Run Code Online (Sandbox Code Playgroud)\n

就时间性能而言,这种特定情况的scipy.spatial.distance.cdist速度要快得多,但并非每个功能都可用:

\n
import numpy as np\nfrom scipy.spatial.distance import cdist\n\na = np.random.random((10_000, 2))\nb = np.random.random((10_000, 2))\n\neuc_broadcast = lambda a,b: np.sqrt(np.sum(np.square(a[:, None]-b[None, :]), axis=-1))\n\n%timeit euc_broadcast(a, b)\n3.39 s \xc2\xb1 149 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n\n%timeit cdist(a, b)\n603 ms \xc2\xb1 13.2 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n