15

Python(numpy)で次の操作を実行しようとしています。

Matrix A is M x N x R
Matrix B is N x 1 x R

行列乗算 AB = C、ここで C は M x 1 x R 行列です。基本的に、A の各 M x N レイヤー (それらの R) は、B の各 N x 1 ベクトルによって個別に行列乗算されます。これはワンライナーであると確信しています。私は tensordot() を使おうとしてきましたが、それは私が期待していない答えを私に与えているようです。

私は Igor Pro で 10 年近くプログラミングしており、現在そのページを Python に変換しようとしています。

4

3 に答える 3

18

ネクロマンシーで申し訳ありませんが、この回答は非常に貴重なnp.einsumを使用して大幅に改善できます。

import numpy as np

D,M,N,R = 1,2,3,4
A = np.random.rand(M,N,R)
B = np.random.rand(N,D,R)

print np.einsum('mnr,ndr->mdr', A, B).shape

いくつかの利点があることに注意してください。まず第一に、高速です。np.einsum は一般的に適切に最適化されていますが、さらに、np.einsum は MxNxR 一時配列の作成を回避するのに十分スマートですが、N の縮小を直接実行します。

しかし、おそらくもっと重要なのは、非常に読みやすいことです。このコードが正しいことに疑いの余地はありません。問題なくもっと複雑にすることもできます。

必要に応じて、ダミーの 'D' 軸を B および einsum ステートメントから単純に削除できることに注意してください。

于 2014-01-28T09:01:40.987 に答える
10

numpy.tensordot()はそれを行う正しい方法です:

a = numpy.arange(24).reshape(2, 3, 4)
b = numpy.arange(12).reshape(3, 1, 4)
c = numpy.tensordot(a, b, axes=[1, 0]).diagonal(axis1=1, axis2=3)

編集:これの最初のバージョンは欠陥があり、このバージョンはより多くのハンを計算し、そのほとんどを捨てます。おそらく、最後の軸に対する Python ループは、それを行うためのより良い方法です。

別の編集:ここでは最善の解決策でnumpy.tensordot()ないという結論に達しました。

c = (a[:,:,None] * b).sum(axis=1)

より効率的になります(ただし、把握するのはさらに困難です)。

于 2011-03-17T20:39:01.227 に答える
2

それを行う別の方法 (私のようにアインシュタイン表記法に慣れていない人にとっては簡単です) はnp.matmul(). 重要なことは、最後の 2 つのインデックスに一致する次元 ((M, N) x (N, 1)) を持つことだけです。この使用np.transpose()例:

M, N, R = 4, 3, 10
A = np.ones((M, N, R))
B = np.ones((N, 1, R))

# have the matching dimensions at the very end
C = np.matmul(np.transpose(A, (2, 0, 1)), np.transpose(B, (2, 0, 1))) 
C = np.transpose(C, (1, 2, 0))

print(A.shape)
# out: #(4, 3, 10)
print(B.shape)
# out: #(3, 1, 10)
print(C.shape)
# out: #(4, 1, 10)
于 2020-05-02T12:20:51.987 に答える