6

私は 2 つの多次元 NumPy 配列ABを持っA.shape = (K, d, N)ていB.shape = (K, N, d)ます。軸 0 ( ) に対して要素ごとの操作を実行したいと思います。その操作は、軸 1 と 2 (および)Kに対する行列乗算です。したがって、結果は の多次元配列になるはずです。単純な実装は次のようになります。d, NN, dCC.shape = (K, d, d)C[k] = np.dot(A[k], B[k])

C = np.vstack([np.dot(A[k], B[k])[np.newaxis, :, :] for k in xrange(K)])

しかし、この実装は遅いです。少し速いアプローチは次のようになります。

C = np.dot(A, B)[:, :, 0, :]

これは、多次元配列のデフォルトの動作を使用し、np.dotshape の配列を提供します(K, d, K, d)。ただし、このアプローチでは必要な応答時間が計算されますK(軸 2 に沿った各エントリは同じです)。漸近的には、最初のアプローチよりも遅くなりますが、オーバーヘッドははるかに少なくなります。また、次のアプローチも認識しています。

from numpy.core.umath_tests import matrix_multiply
C = matrix_multiply(A, B)

ただし、この機能が利用できることを保証するものではありません。したがって、私の質問は、NumPy はこれを効率的に行う標準的な方法を提供していますか? 一般に多次元配列に適用される答えは完璧ですが、この場合のみに固有の答えも素晴らしいでしょう。

編集: @Juh_ が指摘したように、2 番目のアプローチは正しくありません。正しいバージョンは次のとおりです。

C = np.dot(A, B).diagonal(axis1=0, axis2=2).transpose(2, 0, 1)

ただし、オーバーヘッドが追加されるため、小さな行列であっても、最初のアプローチよりも遅くなります。最後のアプローチは、小さな行列と大きな行列のすべてのタイミング テストでロング ショットで勝つことです。より良い解決策が見つからない場合は、numpy.core.umath_testsライブラリ (C で記述) をプロジェクトにコピーすることになるとしても、これを使用することを強く検討しています。

4

4 に答える 4

3

問題の可能な解決策は次のとおりです。

C = np.sum(A[:,:,:,np.newaxis]*B[:,np.newaxis,:,:],axis=2)

でも:

  1. KがdおよびNよりもはるかに大きい場合にのみ、vstackアプローチよりも高速です
  2. メモリの問題である可能性があります。上記のソリューションでは、KxdxNxd 配列が割り当てられます (つまり、合計する前のすべての可能な積のペア)。実際には、メモリが不足していたため、大きな K、d、および N でテストできませんでした。

ところで、次のことに注意してください。

C = np.dot(A, B)[:, :, 0, :]

正しい結果が得られません。結果をこのnp.dotコマンドで得られた結果と比較して最初にメソッドをチェックしたため、だまされました。

于 2012-04-26T13:44:39.810 に答える
1

私のプロジェクトでも同じ問題があります。私が思いついた最高のものは、使用するよりも少し速い(おそらく10%)と思いますvstack

K, d, N = A.shape
C = np.empty((K, d, d))
for k in xrange(K):
    C[k] = np.dot(A[k], B[k])

より良い解決策を見たいのですが、これを行うためにどのように使用tensordotするのかよくわかりません。

于 2012-04-26T18:21:35.497 に答える
0

できるよ

np.matmul(A, B)

https://numpy.org/doc/stable/reference/generated/numpy.matmul.htmlを見てください。

十分な大きさの einsum よりも高速である必要がありますK

于 2020-07-22T10:57:39.440 に答える