numpy matrix vector vermenigvuldiging

Als ik twee numpy arrays van afmetingen (n x n)*(n x 1) vermenigvuldig, krijg ik een matrix van grootte (n x n). Volgens de normale regels voor matrixvermenigvuldiging wordt een (n x 1) vector verwacht, maar ik kan eenvoudigweg geen informatie vinden over hoe dit wordt gedaan in de Numpy-module van Python.

Het punt is dat ik het niet handmatig wil implementeren om de snelheid van het programma te behouden.

Voorbeeldcode wordt hieronder weergegeven:

a = np.array([[ 5, 1 ,3], [ 1, 1 ,1], [ 1, 2 ,1]])
b = np.array([1, 2, 3])
print a*b
   >>
   [[5 2 9]
   [1 2 3]
   [1 4 3]]

Wat ik wil is:

print a*b
   >>
   [16 6 8]

Antwoord 1, autoriteit 100%

Eenvoudigste oplossing

Gebruik numpy.dotof a.dot(b). Bekijk de documentatie hier.

>>> a = np.array([[ 5, 1 ,3], 
                  [ 1, 1 ,1], 
                  [ 1, 2 ,1]])
>>> b = np.array([1, 2, 3])
>>> print a.dot(b)
array([16, 6, 8])

Dit gebeurt omdat numpy-arrays geen matrices zijn en de standaardbewerkingen *, +, -, /elementsgewijs werken op arrays.

Houd er rekening mee dat u numpy.matrix(vanaf begin 2021) waar *wordt behandeld als standaard matrixvermenigvuldiging, is numpy.matrixverouderd en kan in toekomstige releases worden verwijderd.. Zie de opmerking in de bijbehorende documentatie(hieronder weergegeven):

Het wordt niet langer aanbevolen om deze klasse te gebruiken, zelfs niet voor lineaire algebra. Gebruik in plaats daarvan gewone arrays. De klas kan in de toekomst worden verwijderd.

Bedankt @HopeKing.


Andere oplossingen

Weet ook dat er andere opties zijn:

  • Zoals hieronder vermeld, werkt de operator @als je python3.5+ gebruikt zoals je zou verwachten:

    >>> print(a @ b)
    array([16, 6, 8])
    
  • Als je overkill wilt, kun je numpy.einsum. De documentatie geeft je een idee van hoe het werkt, maar eerlijk gezegd begreep ik niet helemaal hoe ik het moest gebruiken totdat ik dit antwoorden er gewoon in mijn eentje mee spelen.

    >>> np.einsum('ji,i->j', a, b)
    array([16, 6, 8])
    
  • Vanaf medio 2016 (numpy 1.10.1) kun je de experimentele numpy.matmul, dat werkt als numpy.dotmet twee belangrijke uitzonderingen: geen scalaire vermenigvuldiging maar het werkt met stapels matrices.

    >>> np.matmul(a, b)
    array([16, 6, 8])
    
  • numpy.innerwerkt op dezelfde manier als numpy.dotvoor matrix-vector vermenigvuldiging maar gedraagt zich andersvoor matrix-matrix en tensor vermenigvuldiging (zie Wikipedia over de verschillen tussen het inproduct en het puntproductin het algemeen of zie dit SO-antwoordbetreffende de implementaties van numpy).

    >>> np.inner(a, b)
    array([16, 6, 8])
    # Beware using for matrix-matrix multiplication though!
    >>> b = a.T
    >>> np.dot(a, b)
    array([[35,  9, 10],
           [ 9,  3,  4],
           [10,  4,  6]])
    >>> np.inner(a, b) 
    array([[29, 12, 19],
           [ 7,  4,  5],
           [ 8,  5,  6]])
    

Zeldzamere opties voor randgevallen

  • Als je tensoren hebt (matrices met een dimensie groter dan of gelijk aan één), kun je numpy.tensordotmet het optionele argument axes=1:

    >>> np.tensordot(a, b, axes=1)
    array([16,  6,  8])
    
  • Gebruik numpy.vdotals je een matrix van complexe getallen hebt, omdat de matrix wordt afgevlakt tot een 1D-array, zal het proberen de complexe geconjugeerde punt te vinden product tussen uw afgeplatte matrix en vector (die zal mislukken vanwege een verkeerde maat n*mversus n).

Other episodes