级联矩阵乘法

时间:2016-09-21 15:37:44

标签: performance numpy matrix-multiplication

关于密集矩阵A和向量e,f的快速乘以A * diag(e)* A ^ T * f的任何建议

这就是我现在所拥有的。

v[:] = 0
for i in range(N):
    for j in range(N):
        v[i] = v[i]+A[i,j]*e[j]*np.dot(A[:,j],f)

谢谢,

2 个答案:

答案 0 :(得分:1)

@rubenvb提出的建议可能是最简单的方法。另一种方法是使用einsum

这是一个例子。我将使用以下aef

In [95]: a
Out[95]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [96]: e
Out[96]: array([-1,  2,  3])

In [97]: f
Out[97]: array([5, 4, 1])

这是您的公式直接转换为numpy代码。它与@ rubenvb的建议基本相同:

In [98]: a.dot(np.diag(e)).dot(a.T).dot(f)
Out[98]: array([ 556, 1132, 1708])

这是einsum版本:

In [99]: np.einsum('ij,j,jk,k', a, e, a.T, f)
Out[99]: array([ 556, 1132, 1708])

您可以通过交换与该参数关联的索引标签来消除转换a的需要:

In [100]: np.einsum('ij,j,kj,k', a, e, a, f)
Out[100]: array([ 556, 1132, 1708])

答案 1 :(得分:1)

@ rubenvb&s的评论,建议使用A.dot(np.diag(e)).dot(A.transpose()).dot(f)的评论应该让它真的很快。但是,我们并不需要在那里2D diag(e)数组,因此跳过一次矩阵乘法。此外,我们可以替换A.Tf的位置,从而避免转置。因此,一个简化且更有效的解决方案将会发展,如此 -

A.dot(e*f.dot(A))

这是在所有提议的方法上对体面大小的阵列进行快速运行时测试 -

In [226]: # Setup inputs
     ...: N = 200
     ...: A = np.random.rand(N,N)
     ...: e = np.random.rand(N,)
     ...: f = np.random.rand(N,)
     ...: 

In [227]: %timeit np.einsum('ij,j,kj,k', A, e, A, f) # @Warren Weckesser's soln
10 loops, best of 3: 77.6 ms per loop

In [228]: %timeit A.dot(np.diag(e)).dot(A.transpose()).dot(f) # @rubenvb's soln
10 loops, best of 3: 18.6 ms per loop

In [229]: %timeit A.dot(e*f.dot(A)) # Proposed here
10000 loops, best of 3: 100 µs per loop