Python 使用形状(x,y,z)和(x,)对numpy数组进行乘法和求和
所以我有一个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拷贝 当前解决方案的示例: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
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)