2016-10-02 80 views
1

我有形状(N*2)的矩阵M1和另一矩阵M2(2*N),我想获得的(N)结果,每个元件ii第i行的乘积M1i第012列的M2。 我试图在NumPy的使用点,但它只能给我的矩阵乘法结果,这是(N*N),当然,我可以采取对角线这是我想要的,我想知道有没有更好的方式来做到这个?计算产品 - NumPy的

回答

1

方法#1

您可以使用np.einsum -

np.einsum('ij,ji->i',M1,M2) 

说明:

原来糊涂的解决方案将是这个样子 -

def original_app(M1,M2): 
    N = M1.shape[0] 
    out = np.zeros(N) 
    for i in range(N): 
     out[i] = M1[i].dot(M2[:,i]) 
    return out 

因此,对于每一次迭代,我们有:

out[i] = M1[i].dot(M2[:,i]) 

在迭代器寻找,我们需要对齐的M1第一轴线与M2第二轴线。同样,因为我们正在执行matrix-multiplication并且由于其本身的定义与的M2第一轴线对准的M1第二轴线,并且还总结减少在每一次迭代这些元素。

当移植到einsum,保持轴的两个输入端之间的对准指定字符串符号给它时具有相同的字符串。所以,输入分别为'ij,ji,M1M2。从M1失去第二串后的输出,这是与从在总和还原M2第一串,应该保留i。因此,完整的字符串符号将为:'ij,ji->i',最终解决方案为:np.einsum('ij,ji->i',M1,M2)

方法2

M1 COLS或行数的在M2数量是2。因此,另外,我们就可以切片,进行逐元素乘法和总结这些,就像这样 -

M1[:,0]*M2[0] + M1[:,1]*M2[1] 

运行测试

In [431]: # Setup inputs 
    ...: N = 1000 
    ...: M1 = np.random.rand(N,2) 
    ...: M2 = np.random.rand(2,N) 
    ...: 

In [432]: np.allclose(original_app(M1,M2),np.einsum('ij,ji->i',M1,M2)) 
Out[432]: True 

In [433]: np.allclose(original_app(M1,M2),M1[:,0]*M2[0] + M1[:,1]*M2[1]) 
Out[433]: True 

In [434]: %timeit original_app(M1,M2) 
100 loops, best of 3: 2.09 ms per loop 

In [435]: %timeit np.einsum('ij,ji->i',M1,M2) 
100000 loops, best of 3: 13 µs per loop 

In [436]: %timeit M1[:,0]*M2[0] + M1[:,1]*M2[1] 
100000 loops, best of 3: 14.2 µs per loop 

大规模加速那里!

+0

不错的答案,让我消化了一段时间。爱因斯坦是强大的,但对于初学者来说似乎并不容易理解。 – 1a1a11a

+0

你能解释一点这是如何工作的?我正在阅读文档,很难理解 – 1a1a11a

+0

@ 1a1a11a查看添加的评论是否有意义。 – Divakar