广播3d数组以进行元素乘法

时间:2018-09-06 18:47:36

标签: python numpy broadcasting

晚上好

我需要一些帮助来理解具有复杂numpy数组的高级广播。

我有:

数组A:50000x2000

数组B:2000x10x10

for循环的实现:

for k in range(50000):
    temp = A[k,:].reshape(2000,1,1)
    finalarray[k,:,:]=np.sum ( B*temp , axis=0)

我想要对具有2000个元素且最终产品的轴进行逐元素乘法和求和:

finalarray:50000x10x10

是否可以避免for循环? 谢谢!

2 个答案:

答案 0 :(得分:7)

对于这样的事情,我将使用np.einsum,这使得根据所需的索引操作写下想要发生的事情变得很容易:

fast = np.einsum('ij,jkl->ikl', A, B)

这给了我相同的结果(删除50000-> 500,这样循环播放就很快完成了):

A = np.random.random((500, 2000))
B = np.random.random((2000, 10, 10))
finalarray = np.zeros((500, 10, 10))
for k in range(500):
    temp = A[k,:].reshape(2000,1,1)
    finalarray[k,:,:]=np.sum ( B*temp , axis=0)

fast = np.einsum('ij,jkl->ikl', A, B)

给我

In [81]: (finalarray == fast).all()
Out[81]: True

即使在50000情况下也具有合理的性能:

In [88]: %time fast = np.einsum('ij,jkl->ikl', A, B)
Wall time: 4.93 s

In [89]: fast.shape

Out[89]: (50000, 10, 10)

或者,在这种情况下,您可以使用tensordot

faster = np.tensordot(A, B, axes=1)

将会快几倍(以降低通用性为代价):

In [29]: A = np.random.random((50000, 2000))

In [30]: B = np.random.random((2000, 10, 10))

In [31]: %time fast = np.einsum('ij,jkl->ikl', A, B)
Wall time: 5.08 s

In [32]: %time faster = np.tensordot(A, B, axes=1)
Wall time: 504 ms

In [33]: np.allclose(fast, faster)
Out[33]: True

在这里我必须使用allclose,因为最终值会略有不同:

In [34]: abs(fast - faster).max()
Out[34]: 2.7853275241795927e-12

答案 1 :(得分:0)

这应该有效:

$('.multi-prod').change(function(e){
  $this = $(this)
  $('.qty').attr('name', $this.val())
})

但是它会耗尽产品创建的中间阵列的内存。

该产品的形状为(A[:, :, None, None] * B[None, :, :]).sum(axis=1) ,因此包含100亿个元素,对于64位浮点值,这是80 GB。