Numpy einsum menghitung hasil kali luar sepanjang sumbu

Aug 19 2020

Saya memiliki dua array numpy yang berisi matriks yang kompatibel dan ingin menghitung produk luar yang bijak dari elemen menggunakan numpy.einsum . Bentuk dari array tersebut adalah:

A1 = (i,j,k)
A2 = (i,k,j) 

Oleh karena itu array mengandung imatriks bentuk (k,j)dan (j,k)masing - masing.

Jadi diberikan A1akan berisi matriks A,B,Cdan A2akan berisi matriks D,E,F, hasilnya adalah:

A3 = (A(x)D,B(x)E,C(x)F)

Dengan (x)menjadi operator produk luar.

Ini akan menghasilkan pemahaman saya berdasarkan jawaban ini sebuah array A3dari bentuk berikut:

A3 = (i,j*k,j*k)

Sejauh ini saya sudah mencoba:

np.einsum("ijk, ilm -> ijklm", A1, A2)

Namun bentuk yang dihasilkan tidak pas.

Sebagai pemeriksaan kewarasan saya menguji ini:

A = np.asarray(([1,2],[3,4]))
B = np.asarray(([5,6],[7,8]))

AB_outer = np.outer(A,B)

A_vec = np.asarray((A,A))
B_vec = np.asarray((B,B))

# this line is not correct
AB_vec = np.einsum("ijk, ilm -> ijklm", A_vec,B_vec)

np.testing.assert_array_equal(AB_outer, AB_vec[0])

Ini saat ini melempar kesalahan pernyataan karena notasi einsum saya tidak benar. Saya juga terbuka untuk setiap saran yang dapat mengatasi ini dan lebih cepat atau sama cepatnya dengan nimfa einsum.

Jawaban

3 Divakar Aug 19 2020 at 17:46

Kami dapat memperpanjang masa redup dan broadcastingmelakukan pekerjaan untuk kami -

(A1[:,:,None,:,None]*A2[:,None,:,None,:]).swapaxes(2,3)

Contoh run -

In [46]: A1 = np.random.rand(3,4,4)
    ...: A2 = np.random.rand(3,4,4)

In [47]: out = (A1[:,:,None,:,None]*A2[:,None,:,None,:]).swapaxes(2,3)

In [48]: np.allclose(np.multiply.outer(A1[0],A2[0]), out[0])
Out[48]: True

In [49]: np.allclose(np.multiply.outer(A1[1],A2[1]), out[1])
Out[49]: True

In [50]: np.allclose(np.multiply.outer(A1[2],A2[2]), out[2])
Out[50]: True

Setara dengan np.einsumakan -

np.einsum('ijk,ilm->ijklm',A1,A2)
1 Valdi_Bo Aug 20 2020 at 01:07

Anda dapat menghitung hasil dengan berjalan:

result = np.einsum('ijk,ikl->ijl', A1, A2)

Saya memeriksa kode di atas pada data uji berikut:

A = np.arange(1, 13).reshape(3, -1)
B = np.arange(2, 14).reshape(3, -1)
C = np.arange(3, 15).reshape(3, -1)
D = np.arange(1, 13).reshape(4, -1)
E = np.arange(2, 14).reshape(4, -1)
F = np.arange(3, 15).reshape(4, -1)
A1 = np.array([A, B, C])
A2 = np.array([D, E, F])

Hasilnya adalah:

array([[[ 70,  80,  90],
        [158, 184, 210],
        [246, 288, 330]],

       [[106, 120, 134],
        [210, 240, 270],
        [314, 360, 406]],

       [[150, 168, 186],
        [270, 304, 338],
        [390, 440, 490]]])

Sekarang hitung 3 "hasil parsial":

res_1 = A @ D
res_2 = B @ E
res_3 = C @ F

dan periksa apakah bagian tersebut sama dengan bagian yang berurutan dari hasil.