2016-09-21 14 views
1

密行列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) 

おかげで、@rubenvbによって作ら

+1

-

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

をここで提案されたすべてのアプローチにまともなサイズの配列の迅速な実行時のテストです? A.ドット(diag(e))のようなものdot(A.tranpose()).dot(f)? – rubenvb

答えて

1

の提案は、おそらくそれを行うための最も簡単な方法です。別の方法は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 [99]: np.einsum('ij,j,jk,k', a, e, a.T, f) 
Out[99]: array([ 556, 1132, 1708]) 

あなたはその引数に関連付けられたインデックスラベルを交換することによりaを移調する必要性を排除することができます:

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

ここeinsumバージョンです

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

@ rubenvbのコメントでは、A.dot(np.diag(e)).dot(A.transpose()).dot(f)を使用することが推奨されていました。しかし、実際には2Dの配列をdiag(e)にする必要はないので、1つの行列乗算をスキップします。また、A.Tfの場所を入れ替えることもできます。転置も避けてください。このように、単純化されたとはるかに効率的なソリューションはそうのように、進化するだろう - numpyの内積を使用しないのはなぜ

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 
+0

アドバイスをいただきありがとうございます。これはうまくいくはずです。 – Tunneller

+0

@ Tunneller投稿された解決策のいずれかがあなたのために働いた場合は、最も効果的なものを受け入れることを検討してください。回答の受け入れに関する詳細はこちら - http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – Divakar