2013-02-07 2 views
18

2 numpyのアレイを有する想像:nは任意に大きくすることができるが結果の対角線のエントリだけを計算する、numpy/scipyの内積がありますか?

> A, A.shape = (n,p) 
> B, B.shape = (p,p) 

通常pは、少ない数(= 200 P <)です。

私は、次のやっている:あなたが見ることができるように、私はn個の対角エントリを保管しております

result = np.diag(A.dot(B).dot(A.T)) 

、しかし唯一の対角エントリが保持され、そこから計算した中間(N×N個)の配列があります。

私はdiag_dot()のような関数を望んでいますが、これは結果の対角成分だけを計算し、完全なメモリを割り当てません。

結果は次のようになります

> result = diag_dot(A.dot(B), A.T) 

このような既成の機能があり、これは中間体(N×N個)アレイを割り当てる必要とせずに効率的に行うことができますか?スカラー積の個々の合計と同等であるマトリックス乗算

> Z = N.diag(X.dot(Y)) 

の唯一の対角線を取得して以来、

答えて

18

は、私は私が自分でそれを得たと思いますが、それにもかかわらず、解決策を共有しますこの手段元の変数のために

> Z = (X * Y.T).sum(-1) 

:XとYの列の行で、前のステートメントは同等です

> result = (A.dot(B) * A).sum(-1) 

私は間違っているが、これはそれをする必要がありますなら、私を修正してください...

+5

+1スマート代数は常に高度なアルゴリズムよりも優れています。 – Jaime

21

あなたは、あなたが今までnumpy.einsumを夢見ほとんど何を得ることができます。あなたはそれのこつ取得を開始するまで、基本的に...あなたが実際にシングルショットで全部を取得することができます

>>> a = np.arange(15).reshape(5, 3) 
>>> b = np.arange(9).reshape(3, 3) 

>>> np.diag(np.dot(np.dot(a, b), a.T)) 
array([ 60, 672, 1932, 3840, 6396]) 
>>> np.einsum('ij,ji->i', np.dot(a, b), a.T) 
array([ 60, 672, 1932, 3840, 6396]) 
>>> np.einsum('ij,ij->i', np.dot(a, b), a) 
array([ 60, 672, 1932, 3840, 6396]) 

EDITが、それはばかげて...黒魔術のように思える

>>> np.einsum('ij,jk,ki->i', a, b, a.T) 
array([ 60, 672, 1932, 3840, 6396]) 
>>> np.einsum('ij,jk,ik->i', a, b, a) 
array([ 60, 672, 1932, 3840, 6396]) 

EDITあなたは自分自身でそれをあまりにも多く描きたくはありません...比較のためにOP自身の質問にOPの回答を追加しました。大規模な中間アレイの構築を回避

n, p = 10000, 200 
a = np.random.rand(n, p) 
b = np.random.rand(p, p) 

In [2]: %timeit np.einsum('ij,jk,ki->i', a, b, a.T) 
1 loops, best of 3: 1.3 s per loop 

In [3]: %timeit np.einsum('ij,ij->i', np.dot(a, b), a) 
10 loops, best of 3: 105 ms per loop 

In [4]: %timeit np.diag(np.dot(np.dot(a, b), a.T)) 
1 loops, best of 3: 5.73 s per loop 

In [5]: %timeit (a.dot(b) * a).sum(-1) 
10 loops, best of 3: 115 ms per loop 
+0

私はこの機能を知らなかったが、確かにそうするだろう。共有のためのThx! – user2051916

1

歩行者の答えは、次のとおりです。

result=np.empty([n.], dtype=A.dtype) 
for i in xrange(n): 
    result[i]=A[i,:].dot(B).dot(A[i,:]) 
関連する問題