2017-04-14 15 views
2

実際に類似の質問hereherehereがありますが、私はそれらを自分のケースに正確に適用する方法を理解していません。行列とベクトルの要素ワイズドット積

私は行列の配列とベクトルの配列を持っており、要素ごとのドット積が必要です。図:

In [1]: matrix1 = np.eye(5) 

In [2]: matrix2 = np.eye(5) * 5 

In [3]: matrices = np.array((matrix1,matrix2)) 

In [4]: matrices 
Out[4]: 
array([[[ 1., 0., 0., 0., 0.], 
     [ 0., 1., 0., 0., 0.], 
     [ 0., 0., 1., 0., 0.], 
     [ 0., 0., 0., 1., 0.], 
     [ 0., 0., 0., 0., 1.]], 

     [[ 5., 0., 0., 0., 0.], 
     [ 0., 5., 0., 0., 0.], 
     [ 0., 0., 5., 0., 0.], 
     [ 0., 0., 0., 5., 0.], 
     [ 0., 0., 0., 0., 5.]]]) 

In [5]: vectors = np.ones((5,2)) 

In [6]: vectors 
Out[6]: 
array([[ 1., 1.], 
     [ 1., 1.], 
     [ 1., 1.], 
     [ 1., 1.], 
     [ 1., 1.]]) 

In [9]: np.array([m @ v for m,v in zip(matrices, vectors.T)]).T 
Out[9]: 
array([[ 1., 5.], 
     [ 1., 5.], 
     [ 1., 5.], 
     [ 1., 5.], 
     [ 1., 5.]]) 

この最後の行は私の出力です。残念なことに、ブロードキャストのために望ましくないドット積を計算するmatrices @ vectorsを実行すると、非常に効率が悪くなります(私がよく分かっていれば、2つのベクトルの最初の行列ドットと2つのベクトルの2番目の行列ドットを返します)

私はnp.einsumまたはnp.tensordotがここで役に立つかもしれませんと思いますが、私のすべての試みが失敗した:

In [30]: np.einsum("i,j", matrices, vectors) 
ValueError: operand has more dimensions than subscripts given in einstein sum, but no '...' ellipsis provided to broadcast the extra dimensions. 

In [34]: np.tensordot(matrices, vectors, axes=(0,1)) 
Out[34]: 
array([[[ 6., 6., 6., 6., 6.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.]], 

     [[ 0., 0., 0., 0., 0.], 
     [ 6., 6., 6., 6., 6.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.]], 

     [[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 6., 6., 6., 6., 6.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.]], 

     [[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 6., 6., 6., 6., 6.], 
     [ 0., 0., 0., 0., 0.]], 

     [[ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0.], 
     [ 6., 6., 6., 6., 6.]]]) 

NB:私の本当の場合のシナリオはnp.einsummatrix1matrix2

答えて

3

よりも複雑行列を使用し、あなたは使用する可能性があります:

np.einsum("ijk,ki->ji", matrices, vectors) 

#array([[ 1., 5.], 
#  [ 1., 5.], 
#  [ 1., 5.], 
#  [ 1., 5.], 
#  [ 1., 5.]]) 
+0

私はそれだと思います。私は私が推測するこのアインシュタイン表記で作業しなければならない...ありがとう! – nicoco

+0

ようこそ。うれしい! – Psidom

1

@は次のように使用できます。次のようになります。

matrices @ vectors.T[..., None] 
# array([[[ 1.], 
#   [ 1.], 
#   [ 1.], 
#   [ 1.], 
#   [ 1.]], 

#  [[ 5.], 
#   [ 5.], 
#   [ 5.], 
#   [ 5.], 
#   [ 5.]]]) 

わかりましたが、正しいものを計算しますが、それらを間違って配置しています。 したがって

(matrices @ vectors.T[..., None]).squeeze().T 
# array([[ 1., 5.], 
#  [ 1., 5.], 
#  [ 1., 5.], 
#  [ 1., 5.], 
#  [ 1., 5.]]) 
+0

これも機能し、明らかに@Psidomの解決策と同じくらい速いです。私は彼がより速かったので、彼の答えを受け入れるでしょうが、これは同等に良いです... – nicoco

+0

@nicoco私と一緒に罰金。タイミングを取ってくれてありがとう。それは知っておくと便利です。 –

関連する問題