Python 使用形状(x,y,z)和(x,)对numpy数组进行乘法和求和

Python 使用形状(x,y,z)和(x,)对numpy数组进行乘法和求和,python,arrays,numpy,optimization,linear-algebra,Python,Arrays,Numpy,Optimization,Linear Algebra,所以我有一个3D数据集(x,y,z),我想在其中一个轴(x)上加一组权重,w=w(x)。我求和的开始和结束索引对于每个(y,z)都是不同的,我通过屏蔽3D数组解决了这个问题。对于我没有求和的两个变量,权重是恒定的。关于实现和数学的两个答案都是值得赞赏的(是否有一个聪明的linalg。这样做的方法?) 我有一个形状为(x,y,z)的3D掩蔽阵列(a)和形状为(x,)的一维阵列(t)。有没有一种好方法可以将a中的每个(y,z)元素与t中的相应数字相乘,而不将t扩展到三维数组?我目前的解决方案是使用n

所以我有一个3D数据集(x,y,z),我想在其中一个轴(x)上加一组权重,w=w(x)。我求和的开始和结束索引对于每个(y,z)都是不同的,我通过屏蔽3D数组解决了这个问题。对于我没有求和的两个变量,权重是恒定的。关于实现和数学的两个答案都是值得赞赏的(是否有一个聪明的linalg。这样做的方法?)

我有一个形状为(x,y,z)的3D掩蔽阵列(a)和形状为(x,)的一维阵列(t)。有没有一种好方法可以将a中的每个(y,z)元素与t中的相应数字相乘,而不将t扩展到三维数组?我目前的解决方案是使用np.tensordot制作一个与a形状相同的3D数组,它保存了所有的t值,但是花费运行时间构建“新的t”数组感觉非常不满意,它本质上只是t的y*z拷贝

当前解决方案的示例:

a1 = np.array([[1,2,3,4],
               [5,6,7,8],
               [9,10,11,12]])

a2 = np.array([[0,1,2,3],
               [4,5,6,7],
               [8,9,10,11]])

#note: A is a masked array, mask is a 3D array of bools
A = np.ma.masked_array([a1,a2],mask)
t = np.array([10,11])

new_t = np.tensordot(t, np.ones(A[0].shape), axes = 0)
return np.sum(A*new_t, axis=0)
本质上,我希望以尽可能短的运行时间为所有i,j执行t*A[:,i,j],最好不要使用numpy和scipy以外的太多库

产生所需输出的另一种方法(同样,运行时间太长):


灵感来自@phipsgabler评论

arr1 = np.tensordot(A.T,t,axes=1).T
arr1
array([[ 10,  31,  52,  73],
       [ 94, 115, 136, 157],
       [178, 199, 220, 241]])

谢谢你的回答!使用像@alyhosny这样的tensordot是可行的,但使用

A = np.ma.MaskedArray.filled(A,0)
在与einsum求和之前(感谢@phipsgabler),他给出了一半的运行时间。最终代码:

A = np.ma.MaskedArray(A,mask)
A = np.ma.MaskedArray.filled(A,0)
return np.einsum('ijk,i->jk',A,t)

类似于
np.einsum('ijk,i->jk',A,t)
?谢谢!现在编辑,A是一个蒙版数组,看起来einsum不关心蒙版。尽管如此,einsum似乎还是一个不错的选择。只要有正确的广播技巧,即使只是
tensordot
也可能奏效。这通常只是一些虚拟数据的试验结束错误。。。这就是为什么我懒得这么做并写一个答案:)我在发帖前已经试了好几个小时,这就是为什么我想知道是否有更好的方法。Einsum就像一个符咒,只是它使用了隐藏的值。对于
Einsum
matmul
@
),
tensordot
不再有用了。基本上,
tensordot
对输入进行重塑和转换,以生成兼容的数组。然后,它将结果转换回更多的重塑和转置。谢谢!这是可行的,我想关于使用tensordot(和其他np-linalg函数)我还有很多要学习的地方:)但我想我可以在求和之前用零代替掩码填充掩码数组,这就给了运行时间的一半以下:)
A = np.ma.MaskedArray(A,mask)
A = np.ma.MaskedArray.filled(A,0)
return np.einsum('ijk,i->jk',A,t)