Produk titik untuk array NumPy berbentuk sewenang-wenang

Diberikan dua objek numpy.ndarray, A dan B, dengan bentuk sembarang, saya ingin menghitung numpy.ndarray C dengan properti yang C[i] == np.dot(A[i], B[i]) untuk semua i. Bagaimana saya bisa melakukan ini?

Contoh 1: A.shape==(2,3,4) dan B.shape==(2,4,5), maka kita harus memiliki C.shape==(2,3,5).

Contoh 2: A.shape==(2,3,4) dan B.shape==(2,4), maka kita harus memiliki C.shape==(2,3).


person dshin    schedule 20.06.2016    source sumber
comment
Jadi bentuk A dan B tidak sepenuhnya sembarangan. Mereka diharuskan memiliki bentuk yang kompatibel di setiap i. Yaitu, A.shape[0] == B.shape[0] harus True   -  person piRSquared    schedule 20.06.2016
comment
einsum('ijk,ik...->ij...',A,B) menangani 2 kasus Anda. Itu hanya membatasi A menjadi 3d, B bisa menjadi 2,3, dst.   -  person hpaulj    schedule 21.06.2016


Jawaban (2)


Berikut adalah solusi umum untuk mencakup semua jenis kasus/bentuk arbitrer menggunakan beberapa reshaping dan np.einsum. einsum membantu di sini karena kita memerlukan penyelarasan sepanjang sumbu pertama dan pengurangan sepanjang sumbu terakhir dari array input. Implementasinya akan terlihat seperti ini -

def dotprod_axis0(A,B):
    N,nA,nB = A.shape[0], A.shape[-1], B.shape[1]
    Ar = A.reshape(N,-1,nA)
    Br = B.reshape(N,nB,-1)
    return np.squeeze(np.einsum('ijk,ikl->ijl',Ar,Br))

Kasus

Saya. A : 2D, B : 2D

In [119]: # Inputs
     ...: A = np.random.randint(0,9,(3,4))
     ...: B = np.random.randint(0,9,(3,4))
     ...: 

In [120]: for i in range(A.shape[0]):
     ...:     print np.dot(A[i], B[i])
     ...:     
33
86
48

In [121]: dotprod_axis0(A,B)
Out[121]: array([33, 86, 48])

II. J : 3D, B : 3D

In [122]: # Inputs
     ...: A = np.random.randint(0,9,(2,3,4))
     ...: B = np.random.randint(0,9,(2,4,5))
     ...: 

In [123]: for i in range(A.shape[0]):
     ...:     print np.dot(A[i], B[i])
     ...:     
[[ 74  70  53 118  43]
 [ 47  43  29  95  30]
 [ 41  37  26  23  15]]
[[ 50  86  33  35  82]
 [ 78 126  40 124 140]
 [ 67  88  35  47  83]]

In [124]: dotprod_axis0(A,B)
Out[124]: 
array([[[ 74,  70,  53, 118,  43],
        [ 47,  43,  29,  95,  30],
        [ 41,  37,  26,  23,  15]],

       [[ 50,  86,  33,  35,  82],
        [ 78, 126,  40, 124, 140],
        [ 67,  88,  35,  47,  83]]])

III. J : 3D, B : 2D

In [125]: # Inputs
     ...: A = np.random.randint(0,9,(2,3,4))
     ...: B = np.random.randint(0,9,(2,4))
     ...: 

In [126]: for i in range(A.shape[0]):
     ...:     print np.dot(A[i], B[i])
     ...:     
[ 87 105  53]
[152 135 120]

In [127]: dotprod_axis0(A,B)
Out[127]: 
array([[ 87, 105,  53],
       [152, 135, 120]])

IV. A : 2D, B : 3D

In [128]: # Inputs
     ...: A = np.random.randint(0,9,(2,4))
     ...: B = np.random.randint(0,9,(2,4,5))
     ...: 

In [129]: for i in range(A.shape[0]):
     ...:     print np.dot(A[i], B[i])
     ...:     
[76 93 31 75 16]
[ 33  98  49 117 111]

In [130]: dotprod_axis0(A,B)
Out[130]: 
array([[ 76,  93,  31,  75,  16],
       [ 33,  98,  49, 117, 111]])
person Divakar    schedule 20.06.2016
comment
Secara umum, np.dot(x,y) dapat terdefinisi dengan baik bahkan ketika len(x.shape)›2 dan bahkan ketika len(x.shape)!=len(y.shape). Dalam praktiknya, saya mungkin dapat menentukan if/else berdasarkan bentuk A dan B untuk beberapa kasus yang saat ini saya pedulikan tetapi berharap tidak melakukan itu. - person dshin; 20.06.2016
comment
@dshin Ya! Beberapa pembentukan kembali mungkin bisa membantu. - person Divakar; 20.06.2016
comment
@dshin Lihat kode yang diedit untuk mencakup semua kasus! - person Divakar; 21.06.2016

Dengan asumsi Anda menginginkan perkalian matriks biasa untuk dot (bukan, katakanlah, vektor-matriks atau omong kosong aneh yang dot lakukan untuk dimensi yang lebih tinggi), maka versi NumPy yang cukup baru (1.10+) memungkinkan Anda melakukannya

C = numpy.matmul(A, B)

dan versi Python yang cukup baru (3.5+) memungkinkan Anda menulisnya sebagai

C = A @ B

dengan asumsi NumPy Anda juga cukup baru.

person user2357112 supports Monica    schedule 20.06.2016
comment
Saya menambahkan beberapa contoh ke OP, salah satunya memiliki vektor matriks. - person dshin; 20.06.2016