J'ai deux tableaux numériques 2D A et B avec les dimensions suivantes (row, cols)

A.shape = (3000, 128) et B.shape = (5000, 128)

Je souhaite prendre le produit scalaire pour chaque ligne de A avec chaque ligne de B. Tels que;

np.dot(A[0], B[0])
np.dot(A[0], B[1]
np.dot(A[0], B[2]
 .   *  .
 .   *  .  
 .   *  .
np.dot(A[0], B[last]) # last row in B
np.dot(A[1], B[0]) # new row in A
np.dot(A[1], B[1])
np.dot(A[1], B[2])
 .   *  .
 .   *  .  
 .   *  .
np.dot(A[last], B[last]) # last operation

Y a-t-il un nom particulier pour cette opération?

En ce moment, j'ai deux boucles for qui, je suppose, sont assez lentes.

all_dots = []
for i in range(0, len(A)):
    for j in range(0, len(B)):
        all_dots.append(np.dot(B[j], A[i]))

Je recherche peut-être une opération native en algèbre linéaire qui résout ce problème plus efficacement.

Merci d'avance!

2
Isbister 26 mai 2020 à 03:02

4 réponses

Meilleure réponse

C'est un produit matriciel. Le nombre de colonnes de la première matrice doit être égal au nombre de lignes de la seconde

np.dot(A, B.transpose())

Ce qui donne un équivalent de ce que fait votre code avec deux boucles imbriquées. Une autre façon consiste à utiliser un opérateur de multiplication matricielle @ et un raccourci .T pour .transpose()

A @ B.T

Ou la méthode .dot() d'un tableau numpy

A.dot(B.transpose())

Cudos à Dan!

4
Aramakus 26 mai 2020 à 10:16

Si vous voulez toutes les combinaisons, vous pouvez profiter de la diffusion comme ceci:

np.sum(A.reshape(1, 2, 2) * B.reshape(3, 1, 2), axis=2)

Qui aura tous les mêmes éléments que votre all_dots si vous l'aplatissez.

0
Dan 26 mai 2020 à 00:31

Vous pouvez également utiliser l'infâme einsum:

np.einsum('ij,kj->ik', a,b)

Tester:

a, b = np.arange(12).reshape(3,4), np.arange(16).reshape(4,4)

np.einsum('ij,kj->ik', a,b)

Production:

array([[ 14,  38,  62,  86],
       [ 38, 126, 214, 302],
       [ 62, 214, 366, 518]])

Si vous voulez un tableau 1D, enchaînez-le avec un .flatten() ou ravel():

np.einsum('ij,kj->ik', a,b).ravel()

Production:

array([ 14,  38,  62,  86,  38, 126, 214, 302,  62, 214, 366, 518])
2
Quang Hoang 26 mai 2020 à 00:39

Répétez les valeurs A avec len(B) le long de axis = 0, A.repeat(len(B), axis=0) @ B.T


A = np.array([[1,2], [3, 4]])

B = np.array([[1,2, 5, 6], [3, 4]])


A = A.repeat(len(B), axis=0)

A

array([[1, 2],
       [1, 2],
       [3, 4],
       [3, 4]])
-1
m-zayan 26 mai 2020 à 00:51