Python 求向量场大小(长度)平方的最快方法

Python 求向量场大小(长度)平方的最快方法,python,math,optimization,vector,numpy,Python,Math,Optimization,Vector,Numpy,我有一个大的向量场,其中向量场很大(例如512^3;但不一定是正方形),向量是2D或3D(例如形状是[512,512,512,2]或[512,512,3]) 计算向量平方大小的标量场的最快方法是什么 我可以在每个方向上循环,即 import numpy as np shp = [256,256,256,3] # Shape of vector field vf = np.arange(3*(256**3)).reshape(shp) # Cre

我有一个大的向量场,其中向量场很大(例如512^3;但不一定是正方形),向量是2D或3D(例如形状是[512,512,512,2]或[512,512,3])

计算向量平方大小的标量场的最快方法是什么

我可以在每个方向上循环,即

import numpy as np
shp = [256,256,256,3]                       # Shape of vector field
vf = np.arange(3*(256**3)).reshape(shp)     # Create vector field
sf = np.zeros(shp[:3])                      # Create scalar field for result

for ii in range(shp[0]):
    for jj in range(shp[1]):
        for kk in range(shp[2]):
            sf[ii,jj,kk] = np.dot( vf[ii,jj,kk,:] , vf[ii,jj,kk,:] )

但是这相当慢,有更快的吗?

最快的可能是:

上面的代码告诉numpy获取其输入,并通过将相应的值相乘并相加来减少每个输入的最后一个维度。数据集存在溢出问题,因为大小不适合32位整数,这是
np.arange
的默认返回值。您可以通过将返回数据类型指定为
np.int64
np.double
来解决这个问题:

>>> np.einsum('...j,...j->...', vf,vf)[-1, -1, -1]
-603979762
>>> np.einsum('...j,...j->...', vf,vf).dtype
dtype('int32')

>>> np.einsum('...j,...j->...', vf,vf, dtype=np.int64)[-1, -1, -1]
7599823767207950
>>> np.einsum('...j,...j->...', vf,vf, dtype=np.double)[-1, -1, -1]
7599823767207950.0

你的问题与此类似吗?谢谢@Jaime,你能解释一下这是什么意思和/或为什么它是最佳的吗?哇
einsum
刚刚完成了我的一周。另一种可能更明确的方法是使用
np.sum(vf*vf,axis=-1)
。但是,快速测试(对于给定的数组大小)表明,
einsum
版本的速度是原来的两倍多(我猜是因为它避免了使用临时
vf*vf
数组)。@bogatron einsum可以使用SSE2,而numpy UFUNC不在1.7中,请参阅。@Ophion感谢链接。这是非常有益的。如果您对此有不同的解释,请纠正我,但您在链接中显示的结果向我表明,我的上述评论仍然有效,因为这里提出的问题最接近您的上一个示例,对于该示例,einsum仍然比ufunc解决方案快得多(即使使用SSE2)。
>>> np.einsum('...j,...j->...', vf,vf)[-1, -1, -1]
-603979762
>>> np.einsum('...j,...j->...', vf,vf).dtype
dtype('int32')

>>> np.einsum('...j,...j->...', vf,vf, dtype=np.int64)[-1, -1, -1]
7599823767207950
>>> np.einsum('...j,...j->...', vf,vf, dtype=np.double)[-1, -1, -1]
7599823767207950.0