2016-02-02 2 views
5

numpyでは、2次元または3次元のいずれかの配列を持ちますが、各要素を二乗する際に2次元に縮小したいと考えています。だから私はこれを試してみましたが、それは動作しません:それは、このエラーを返すnumpy.einsumの省略記号ブロードキャストディメンションを合計する

A = np.random.rand(5, 3, 3) 
np.einsum('...ij,...ij->ij', A, A) 

ValueError: output has more dimensions than subscripts given in einstein sum, but no '...' ellipsis provided to broadcast the extra dimensions. 

私はeinsumが想定していないと仮定し、省略記号が右側に離れて行くときに、Iそれらが存在する場合、省略記号の次元を合計したい2-D用

A = np.random.rand(5, 3, 3) 
np.einsum('aij,aij->ij', A, A) 

と、この:私は3-Dのためにこれをしたいということを伝えるために(すなわち、次元の数をチェックし、if文使用せずに)いくつかの「エレガント」な方法はありますか?

A = np.random.rand(3, 3) 
np.einsum('ij,ij->ij', A, A) 

答えて

3

時々変数の次元を処理するために、「エレガント」な方法は、if一連のテストを使用して、関数呼び出しでそれらを非表示にすることです。例えばnp.atleast_3dを見てください。 4way if/else節があります。私はここでそれをお勧めしますが、最後に余分な次元を追加します。 ifreshapeを使用する節は高価ではありません(時間がかかる)ので、使用するのを恐れないでください。いくつかの魔法の機能を見つけたとしても、そのコードを見てください。あなたは隠されているものに驚くかもしれません。


省略記号は「乗るために一緒に行く」の寸法ではなく、あなたが特定のコントロールをしたいもののために使用されています。ここでは、最初の次元を超える合計したいので、あなたが明示的にインデックスにそれを必要とする:

In [161]: np.einsum('i...,i...',A,A) 
Out[161]: 
array([[ 1.26942035, 1.32052776, 1.74118617], 
     [ 1.59679765, 1.49331565, 2.04573002], 
     [ 2.29027005, 1.48351522, 1.36679208]]) 
In [162]: np.einsum('aij,aij->ij',A,A) 
Out[162]: 
array([[ 1.26942035, 1.32052776, 1.74118617], 
     [ 1.59679765, 1.49331565, 2.04573002], 
     [ 2.29027005, 1.48351522, 1.36679208]]) 

2D配列の場合:

In [165]: np.einsum('ij,ij->ij',A[0],A[0]) 
Out[165]: 
array([[ 0.20497776, 0.11632197, 0.65396968], 
     [ 0.0529767 , 0.24723351, 0.27559647], 
     [ 0.62806525, 0.33081124, 0.57070406]]) 
In [166]: A[0]*A[0] 
Out[166]: 
array([[ 0.20497776, 0.11632197, 0.65396968], 
     [ 0.0529767 , 0.24723351, 0.27559647], 
     [ 0.62806525, 0.33081124, 0.57070406]]) 
In [167]: 
In [167]: np.einsum('...,...',A[0],A[0]) 
Out[167]: 
array([[ 0.20497776, 0.11632197, 0.65396968], 
     [ 0.0529767 , 0.24723351, 0.27559647], 
     [ 0.62806525, 0.33081124, 0.57070406]]) 

私はあなたが一つの式で両方のケースを扱うことができるとは思いません。第1の和

In [168]: (A*A).sum(axis=0) 
Out[168]: 
array([[ 1.26942035, 1.32052776, 1.74118617], 
     [ 1.59679765, 1.49331565, 2.04573002], 
     [ 2.29027005, 1.48351522, 1.36679208]]) 

を取得する

別の方法私は省略記号の取り扱いを修正したパッチを貢献し、それは数年前でした。だから、細部は私の心の中で新鮮ではありません。その一環として、私はより明確な答えが必要な場合は、文字列式の解析(オリジナルはコンパイルされています)をリバースエンジニアリングし、そのコードをレビュー(または参照してください)できます。出力は、寸法や...が欠落しているので -


In [172]: np.einsum('...ij,...ij->ij',A,A) 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-172-dfe39e268402> in <module>() 
----> 1 np.einsum('...ij,...ij->ij',A,A) 

ValueError: output has more dimensions than subscripts given in 
einstein sum, but no '...' ellipsis provided to broadcast 
the extra dimensions. 
In [173]: np.einsum('...ij,...ij->...ij',A,A).shape 
Out[173]: (5, 3, 3) 

エラーメッセージ

は、出力に ...寸法を渡そうとし、することはできませんされていることを述べています。つまり、 ...次元以上の合計は実行されません。彼らは出力にそのまま渡されます(放送規則が適用されます)。

+0

ありがとう、私はちょうどifステートメントを使用して、私はちょうどこのケースについて興味があったので、einsum関数は配列操作を行う宣言的方法であり、多くの他の配列ライブラリ/言語。私はあなたがhttps://github.com/numpy/numpy/issues/2455(注2)でリインズ・エンジニアリングのeinsumをしていたときに、この事件を少し前に持ち出したことが分かりました。私は、このケースを扱うためにエインサムを拡張することにどのくらいの関心があるのだろうか、例えば、加算可能なラベルを持つオプションのディメンションなど、どれくらいの興味があるのだろうか。おそらく最適化するのは難しいでしょう。 – firescape

関連する問題