在 Python 中有效地找到两个数组的 L3 范数

Find L3 norm of two arrays efficiently in Python

假设我有两个数组。 A 的大小为 n x d,B 的大小为 t x d。假设我想输出一个数组 C,其中 C[i, j] 给出 A[i] 和 B[j] 之间的立方 L3 范数(它们的大小都是 d)。即

C[i, j] = |A[i, 0]-B[j, 0]|**3 + |A[i, 1]-B[j, 1]|**3 + ... + |A[i, d-1]-B[j, d-1]|**3

任何人都可以将我重定向到一个真正有效的方法吗?我试过使用双 for 循环和一些带有数组操作的东西,但是运行时间非常慢。

编辑:我知道 TensorFlow.norm 可行,但我如何自己实现它?

可能会进行一些优化来加快速度,但性能不会接近专业数学包。这些包使用 blas 和 lapack 来向量化操作。它们还通过在您设置值时强制执行类型来避免大量类型检查开销。如果性能很重要,那么您真的没有比像 numpy 这样的数值计算包做得更好的方法了。

根据@gph的回答,Numpy的np.linalg.norm应用的显式示例,使用广播来避免任何循环:

import numpy as np

n, m, d = 200, 300, 3
A = np.random.random((n,d))
B = np.random.random((m,d))
    
C = np.linalg.norm(A[:,None,:] - B[None,...], ord=3, axis = -1)
# The 'raw' option would be:
C2 = (np.sum(np.abs(A[:,None,:] - B[None,...])**3, axis = -1))**(1/3)

这两种方式的执行时间似乎差不多。我试过使用 np.einsum,但我只能说我的代数技能有了长足的进步。也许你运气更好(一个很好的资源是 Divakar 的 wiki)。

使用用 C 编写的第 3 方库或创建您自己的库

numpy has a linalg library 应该能够计算每个 A[i]-B[j]

的 L3 范数

如果 numpy 适合你,看看 numba's JIT,它可以编译和缓存一些 (numpy) 代码,使其速度提高几个数量级(连续运行将利用它) .我相信您需要将要加速的部分描述为将被多次调用以利用它的函数。

大致

import numpy as np
from numpy import linalg as LA
from numba import jit as numbajit

@numbajit
def L3norm(A, B, i, j):
    return LA.norm([A[i] - B[j]], ord=3)

# may be able to apply JIT here too
def operate(A, B, n, t):
    # generate array
    C = np.zeros(shape=(n, t))

    for i in range(n):
        for j in range(t):
            C[i, j] = L3norm(A, B, i, j)

    return C