4

我想在numpy中做两个二维数组的元素明智的外积。numpy元素外部产品

A.shape = (100, 3) # A numpy ndarray 
B.shape = (100, 5) # A numpy ndarray 

C = element_wise_outer_product(A, B) # A function that does the trick 
C.shape = (100, 3, 5) # This should be the result 
C[i] = np.outer(A[i], B[i]) # This should be the result 

一个天真的实现可以如下。

tmp = [] 
for i in range(len(A): 
    outer_product = np.outer(A[i], B[i]) 
    tmp.append(outer_product) 
C = np.array(tmp) 

来自堆栈溢出的更好解决方案。

big_outer = np.multiply.outer(A, B) 
tmp = np.swapaxes(tmp, 1, 2) 
C_tmp = [tmp[i][i] for i in range(len(A)] 
C = np.array(C_tmp) 

我正在寻找摆脱for循环的矢量化实现。 有没有人有想法? 谢谢!

+0

对于它的价值,'np.multiply.outer(A,B)'是'到不同np.outer ',赋予形状'100,3,100,5' – Eric

回答

7

扩展AB3D保持他们的第一轴线对齐,并且沿所述第三和第二个与None/np.newaxis分别引入新的轴,然后彼此相乘。这将允许broadcasting发挥矢量化解决方案的作用。

因此,实现将是 -

A[:,:,None]*B[:,None,:] 

我们可以使用ellipsis为A的缩短了一点::,:,并跳过与B上市剩最后一个轴,像这样 -

A[...,None]*B[:,None] 

至于另一量化的方法,我们还可以使用np.einsum,一旦我们得到过去的字符串表示法,这可能是更直观语法和考虑这些符号被卷入一个天真糊涂实现迭代器的代表,像这样 -

np.einsum('ij,ik->ijk',A,B) 
+0

或'np.einsum( '...,J,...,K - > ... JK',A,B)'到超过3名维工作 – Eric

+0

这些方法都不比循环更快。 'Einsum'对于一个数组来说需要900ms,一个简单的'loop'需要700ms。 'A [:,:,无] * B [:,无,:]'大约是800。 – Swift