n個の正方行列A1、...、Anがあるとします。これらの行列をきちんと乗算する方法はありますか?私の知る限り、numpyのドットは2つの引数しか受け入れません。明らかな方法の1つは、それ自体を呼び出して結果を取得する関数を定義することです。それを成し遂げるためのより良い方法はありますか?
5 に答える
これは比較的最近の機能かもしれませんが、私は次のことを気に入っています。
A.dot(B).dot(C)
または、長いチェーンがある場合は、次のことができます。
reduce(numpy.dot, [A1, A2, ..., An])
アップデート:
reduce hereに関する詳細情報があります。役立つ例を次に示します。
>>> A = [np.random.random((5, 5)) for i in xrange(4)]
>>> product1 = A[0].dot(A[1]).dot(A[2]).dot(A[3])
>>> product2 = reduce(numpy.dot, A)
>>> numpy.all(product1 == product2)
True
2016 年更新: Python 3.5 の時点で、新しい matrix_multiply シンボルがあり@
ます。
R = A @ B @ C
古い質問を更新して復活させる:
2014 年 11 月 13 日の時点で、np.linalg.multi_dot
必要な機能を正確に実行できる関数が追加されました。また、呼び出し順序を最適化するという利点もありますが、あなたの場合は必要ありません。
これは、numpy バージョン 1.10 以降で使用できることに注意してください。
すべての行列を事前に計算する場合は、行列の連鎖乗積の最適化スキームを使用する必要があります。このウィキペディアの記事を参照してください。
これを達成する別の方法は、NumPyのアインシュタイン総和規則einsum
を実装するを使用することです。
この問題に関してこの規則を非常に簡単に説明すると、次のようになります。複数の行列積を積の 1 つの大きな和として書き出すと、次のようになります。
P_im = sum_j sum_k sum_l A1_ij A2_jk A3_kl A4_lm
ここP
で、 は積の結果、A1
、A2
、A3
、およびA4
は入力行列です。加数に 2 回現れるインデックス、つまりj
、k
、およびを正確に合計することに注意してくださいl
。このプロパティを持つ合計は、物理学、ベクトル計算、およびおそらく他の分野でよく見られるため、そのための NumPy ツール、つまり がありeinsum
ます。
上記の例では、次のようにマトリックス積を計算するために使用できます。
P = np.einsum( "ij,jk,kl,lm", A1, A2, A3, A4 )
ここで、最初の引数は関数にどのインデックスを引数行列に適用するかを伝え、次にすべての二重に現れるインデックスが合計され、望ましい結果が得られます。
計算効率はいくつかの要因に依存することに注意してください (したがって、おそらくテストするだけで十分です)。
A_list = [np.random.randn(100, 100) for i in xrange(10)]
B = np.eye(A_list[0].shape[0])
for A in A_list:
B = np.dot(B, A)
C = reduce(np.dot, A_list)
assert(B == C)