4

numpyで2つの2次元配列の要素的な外積を行いたい。numpy要素単位の外積

A.shape = (100, 3) # A numpy ndarray 
B.shape = (100, 5) # A numpy ndarray 

C = element_wise_outer_product(A, B) # A function that does the trick 
C.shape = (100, 3, 5) # This should be the result 
C[i] = np.outer(A[i], B[i]) # This should be the result 

単純な実装では以下のことが可能です。

スタックオーバーフローからより良い解決策が得られました。

big_outer = np.multiply.outer(A, B) 
tmp = np.swapaxes(tmp, 1, 2) 
C_tmp = [tmp[i][i] for i in range(len(A)] 
C = np.array(C_tmp) 

私はforループを取り除くベクトル化された実装を探しています。 誰かがアイデアを持っていますか? ありがとうございました!

+0

- そうのような、素朴な愚かな実装に関わるイテレータの代表者であること、それらの表記法を構文と考えます'、' 100,3,100,5 'の形を与えます – Eric

答えて

7

その第一の軸が整列保持しNone/np.newaxisと第3及び第二のものに沿って新たな軸を導入3DABを拡張した後、互いに掛けます。これにより、ベクター化されたソリューションではbroadcastingが有効になります。

したがって、実装は次のようになります -

A[:,:,None]*B[:,None,:] 

我々はそれをAさんのためellipsisを使用して、ビット短縮できます:,:をしてBで残り最後の軸をリスト飛ばし、そのように -

A[...,None]*B[:,None] 

もう1つのベクトル化手法として、np.einsumを使用することもできます。これは、文字列表記を過ぎると直感的になります`np.multiply.outerは(a、b)は` `np.outerに異なっている、それは価値がある何のため

np.einsum('ij,ik->ijk',A,B) 
+0

3次元以上で動作する 'np.einsum(' ... j、... k - > ... jk '、A、B)' – Eric

+0

これらの方法のどれもループより速いものはありません。 'Einsum'はアレイに対して900msかかるが、ここでは単純なループが700msかかる。 'A [:、:、None] * B [:、None、:]'は約800です。 – Swift