2017-08-28 14 views
2

私は3つの行列WHVを持っています。私はVのすべての列とWの各列の間に要素ごとの乗算を格納し、行ごとに合計を行うkeepを取得したいと考えています。forループなしで行列Aの各列すべてに行列Bの各列を掛けることはできますか?

VWはまた、6行を有する、6行を有する。6つの要素を有するWの各列は()の6つの要素とV列毎のすべての列を乗算し、行によって結果を合計)

W = np.random.randint(4,6, size=(6, 4)) 
H = np.random.randint(1,3, size=(4, 5)) 
V = np.dot(W,H) + 1  
keep = np.array([]).reshape(0,6) 

print W 
>>[[4 4 5 5] 
[4 4 4 4] 
[4 5 5 4] 
[4 5 5 5] 
[5 4 4 5] 
[5 4 4 5]] 
print V 
>>[[28 33 32 37 24] 
[25 29 29 33 21] 
[28 33 33 37 24] 
[30 35 34 39 25] 
[28 32 32 37 23] 
[28 32 32 37 23]] 

# I want the result from only two from four rows of W 
group = 2 
for k in xrange(group): 
    # multiply all of each column of V by k-th column of W and sum in row 
    keep = np.vstack([keep, sum(V[:,:].T*W[:,k])]) 

print keep, keep.shape 
>>[[ 616. 548. 620. 652. 760. 760.] 
    [ 616. 548. 775. 815. 608. 608.]] (2L, 6L) 

forループなしでできますか? Like sum(V[:,:].T*W[:,0:1]Wの各列は行列Vを段階的に乗算しなければならないので、私は可能ではないと思いますが、誰かがより良いアイデアを持っていると確信しています。

私はforループを避けようとしていますが、これは長いアルゴリズムの一部であり、groupが何百までの場合に超高速になることを願っています。

答えて

2

我々は2つの入力間の整列した第1の軸を維持し、出力にそれを維持する必要があるように、np.einsumに最適のように思える -

np.einsum('ij,ik->ki',V,W) 

サンプル実行 -

In [2]: W = np.random.randint(4,6, size=(6, 4)) 
    ...: H = np.random.randint(1,3, size=(4, 5)) 
    ...: V = np.dot(W,H) + 1  
    ...: keep = np.array([]).reshape(0,6) 
    ...: 

In [5]: group = W.shape[1] 
    ...: for k in xrange(group): 
    ...:  # multiply all of each column of V by k-th column of W and sum in row 
    ...:  keep = np.vstack([keep, sum(V[:,:].T*W[:,k])]) 
    ...:  

In [6]: np.allclose(keep, np.einsum('ij,ik->ki',V,W)) 
Out[6]: True 
+1

うわー!以前はこれを知らなかった下付き文字の間の矢印について少し説明してもらえますか?そして、すべての行列を使いたくない場合は、 'np.einsum( 'ij、ik-> ki'、V、W [:、0:2])のように定義します。 – Jan

+1

@Jan ['このコメント'](https://stackoverflow.com/questions/45896939/using-python-numpy-einsum-to-obtain-dot-product-between-2-matrices/45896957#comment78752868_45896957)添字表記を理解すること。はい、あなたが 'W'の最初の2つの列だけであれば、' np.einsum( 'ij、ik-> ki'、V、W [:、0:2]) 'は動作します。 – Divakar

+0

ありがとうございます。もう一つ物事を聞かせてください。 'keep'の' sum'の前にあれば、分母があります。ここで、 'deno = np.dot(W、H)'( 'keep'は以下のようになります。' keep = np.vstack([keep、sum(VT * W [:、k]).T/deno) 'keep = np.array([])。reshape(0,5)')に変更されました。 'np.einsum'に分母を入力する方法は?私は分裂がある場合、または私は別の何かを使用する必要がありますか? – Jan

関連する問題