82 votes

Comment faire le produit de matrices dans PyTorch

En numpy, je peux faire une simple multiplication de matrice comme ceci :

a = numpy.arange(2*3).reshape(3,2)
b = numpy.arange(2).reshape(2,1)
print(a)
print(b)
print(a.dot(b))

Cependant, lorsque j'essaie de le faire avec les tenseurs PyTorch, cela ne fonctionne pas :

a = torch.Tensor([[1, 2, 3], [1, 2, 3]]).view(-1, 2)
b = torch.Tensor([[2, 1]]).view(2, -1)
print(a)
print(a.size())

print(b)
print(b.size())

print(torch.dot(a, b))

Ce code génère l'erreur suivante :

RuntimeError : taille du tenseur incohérente à /Users/soumith/code/builder/wheel/pytorch-src/torch/lib/TH/generic/THTensorMath.c:503

Avez-vous une idée de la manière dont la multiplication de matrices peut être effectuée dans PyTorch ?

115voto

mexmex Points 2614

Vous êtes à la recherche de

torch.mm(a,b)

Notez que torch.dot() se comporte différemment de np.dot() . Il y a eu quelques discussions sur ce qui serait souhaitable ici . Plus précisément, torch.dot() traite à la fois a et b comme des vecteurs 1D (indépendamment de leur forme originale) et calcule leur produit interne. L'erreur est signalée, car ce comportement fait que la fonction a un vecteur de longueur 6 et votre b un vecteur de longueur 2 ; leur produit interne ne peut donc pas être calculé. Pour la multiplication de matrices dans PyTorch, utilisez torch.mm() . La méthode de Numpy np.dot() est en revanche plus flexible ; il calcule le produit interne pour les tableaux 1D et effectue une multiplication de matrice pour les tableaux 2D.

À la demande générale, la fonction torch.matmul effectue des multiplications de matrices si les deux arguments sont 2D et calcule leur produit scalaire si les deux arguments sont 1D . Pour des entrées de telles dimensions, son comportement est le même que celui de np.dot . Il vous permet également de faire de la diffusion ou matrix x matrix , matrix x vector et vector x vector les opérations par lots. Pour plus d'informations, voir son docs .

# 1D inputs, same as torch.dot
a = torch.rand(n)
b = torch.rand(n)
torch.matmul(a, b) # torch.Size([])

# 2D inputs, same as torch.mm
a = torch.rand(m, k)
b = torch.rand(k, j)
torch.matmul(a, b) # torch.Size([m, j])

5 votes

Puisque c'est une réponse acceptée, je pense que vous devriez inclure torch.matmul. Il effectue le produit scalaire pour les tableaux 1D et la multiplication matricielle pour les tableaux 2D.

47voto

BiBi Points 1193

Si vous souhaitez effectuer une multiplication de matrice (tenseur de rang 2), vous pouvez le faire de quatre manières équivalentes :

AB = A.mm(B) # computes A.B (matrix multiplication)
# or
AB = torch.mm(A, B)
# or
AB = torch.matmul(A, B)
# or, even simpler
AB = A @ B # Python 3.5+

Il y a quelques subtilités. De la Documentation PyTorch :

torch.mm ne diffuse pas. Pour la diffusion des produits matriciels, voir torch.matmul().

Par exemple, vous ne pouvez pas multiplier deux vecteurs unidimensionnels par torch.mm ni de multiplier des matrices en lots (rang 3). À cette fin, vous devez utiliser la fonction plus polyvalente torch.matmul . Pour une liste exhaustive des comportements de diffusion de torch.matmul , voir le documentation .

Pour la multiplication par éléments, vous pouvez simplement faire (si A et B ont la même forme)

A * B # element-wise matrix multiplication (Hadamard product)

7 votes

I amour le caractère unique @ opérateur. w @ x sera mon meilleur choix

8voto

David Jung Points 136

Utilisez torch.mm(a, b) ou torch.matmul(a, b)
Les deux sont identiques.

>>> torch.mm
<built-in method mm of type object at 0x11712a870>
>>> torch.matmul
<built-in method matmul of type object at 0x11712a870>

Il existe une autre option qu'il est bon de connaître. Il s'agit de @ opérateur. @Simon H.

>>> a = torch.randn(2, 3)
>>> b = torch.randn(3, 4)
>>> a@b
tensor([[ 0.6176, -0.6743,  0.5989, -0.1390],
        [ 0.8699, -0.3445,  1.4122, -0.5826]])
>>> a.mm(b)
tensor([[ 0.6176, -0.6743,  0.5989, -0.1390],
        [ 0.8699, -0.3445,  1.4122, -0.5826]])
>>> a.matmul(b)
tensor([[ 0.6176, -0.6743,  0.5989, -0.1390],
        [ 0.8699, -0.3445,  1.4122, -0.5826]])    

Les trois donnent les mêmes résultats.

Liens connexes :
Opérateur de multiplication matricielle
PEP 465 -- Un opérateur infixe dédié pour la multiplication de matrices

0 votes

Sont torch.mm(a,b) , torch.matmul(a,b) et a@b équivalent ? Je ne trouve aucune documentation sur l'opérateur @.

0 votes

Oui, il semble qu'il n'y ait pas de documentation concernant @ opérateur. Mais, il y a plusieurs notations dans le document qui incluent @ qui donnent la sémantique de la multiplication de la matrice. Donc je pense que le @ a été surchargé par PyTorch dans le sens d'une multiplication de matrice.

0 votes

Ajout de liens vers l'opérateur @.

7voto

Nivesh Gadipudi Points 332

Vous pouvez utiliser "@" pour calculer un produit scalaire entre deux tenseurs dans pytorch.

a = torch.tensor([[1,2],
                  [3,4]])
b = torch.tensor([[5,6],
                  [7,8]])
c = a@b #For dot product
c

d = a*b #For elementwise multiplication 
d

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X