Comme son nom l'indique, l'objectif premier de la numpy.dot()
a pour fonction de fournir un résultat scalaire en effectuant une opération de type algèbre linéaire traditionnelle produit scalaire sur deux tableaux de forme identique (m,)
.
Compte tenu de cette finalité première, le documentation de numpy.dot()
parle également de ce scénario comme du premier (le premier point ci-dessous) :
numpy.dot(a, b, out=None)
1. If both a and b are 1-D arrays, it is inner product of vectors (without complex conjugation).
2. If both a and b are 2-D arrays, it is matrix multiplication, but using matmul or a @ b is preferred.
3. If either a or b is 0-D (scalar), it is equivalent to multiply and using numpy.multiply(a, b) or a * b is preferred.
4. If a is an N-D array and b is a 1-D array, it is a sum product over the last axis of a and b.
Votre cas est couvert par le 4 e point ci-dessus (comme indiqué par @hpaulj) dans ses commentaires. Mais cela ne répond toujours pas à votre question de savoir pourquoi le résultat a une forme. (3,)
et non (3,1)
comme vous l'aviez prévu.
Vous êtes en droit d'attendre un résultat en forme de (3,1)
seulement si la forme de B
es (2,1)
. Dans un tel cas, puisque A
a une forme (3,2)
y B
a une forme (2,1)
vous seriez en droit d'attendre une forme de résultat de (3,1)
.
Mais ici, B
a une forme de (2,)
et non (2,1)
. Donc, nous sommes maintenant dans un territoire qui est en dehors de la juridiction des règles habituelles de la multiplication des matrices . Donc, c'est vraiment aux concepteurs de la numpy.dot()
fonction de ce que sera le résultat. Ils auraient pu choisir de traiter cela comme une erreur (" dimension mis-match "). Au lieu de cela, ils ont choisi de traiter ce scénario, comme décrit dans le document cette réponse .
Je cite cette réponse, avec quelques modifications pour relater votre code :
Selon numpy, un tableau 1D n'a qu'une seule dimension et toutes les vérifications sont effectués par rapport à cette dimension. Pour cette raison, nous trouvons que np.dot(A,B) vérifie la deuxième dimension de A par rapport à la première dimension de B.
Ainsi, la vérification serait réussie, et numpy ne traiterait pas cela comme une erreur.
Maintenant, la seule question qui reste est pourquoi la forme du résultat (3,)
et non (3,1)
o (1,3)
.
La réponse à cette question est : en A
qui a la forme (3,2)
nous avons consumed
la dernière partie (2,)
pour effectuer la somme des produits. Le site un-consumed
une partie de la forme de A est (3,)
et donc la forme du résultat de np.dot(A,B)
serait (3,)
. Pour mieux comprendre cela, prenons un autre exemple dans lequel A
a une forme de (3,4,2)
au lieu de (3,2)
la partie non consommée de A
La forme de l'article serait (3,4,)
et le résultat de np.dot(A,B)
serait (3,4,)
au lieu de (3,)
que votre exemple a produit.
Voici le code à vérifier :
import numpy as np
A = np.arange(24).reshape(3,4,2)
print ("A is:\n", A, ", and its shape is:", A.shape)
B = np.array([7,8])
print ("B is:\n", B, ", and its shape is:", B.shape)
C = np.dot(A,B)
print ("C is:\n", C, ", and its shape is:", C.shape)
Le résultat de cette opération est :
A is:
[[[ 0 1]
[ 2 3]
[ 4 5]
[ 6 7]]
[[ 8 9]
[10 11]
[12 13]
[14 15]]
[[16 17]
[18 19]
[20 21]
[22 23]]] , and its shape is: (3, 4, 2)
B is:
[7 8] , and its shape is: (2,)
C is:
[[ 8 38 68 98]
[128 158 188 218]
[248 278 308 338]] , and its shape is: (3, 4)
Voici une autre perspective utile pour comprendre le comportement dans cet exemple :
Le tableau A
de la forme (3,4,2)
peut être visualisé conceptuellement comme un tableau externe de tableaux internes, où le tableau externe a une forme (3,4)
et chaque réseau interne a la forme (2,)
. Sur chacun de ces tableaux intérieurs, le produit scalaire traditionnel sera donc effectué en utilisant le tableau B
(qui a la forme (2,)
et les scalaires résultants sont tous laissés à leurs places respectives, pour former un (3,4)
(la forme de la matrice extérieure). Ainsi, le résultat global de numpy.dot(A,B)
composé de tous ces résultats scalaires en place, aurait la forme suivante (3,4)
.