3 τρόποι πολλαπλασιασμού πινάκων στην Python

Σε αυτό το σεμινάριο, θα μάθετε πώς να πολλαπλασιάζετε δύο πίνακες στην Python.

Θα ξεκινήσετε μαθαίνοντας τη συνθήκη για έγκυρο πολλαπλασιασμό πίνακα και θα γράψετε μια προσαρμοσμένη συνάρτηση Python για να πολλαπλασιάσετε πίνακες. Στη συνέχεια, θα δείτε πώς μπορείτε να επιτύχετε το ίδιο αποτέλεσμα χρησιμοποιώντας ένθετες κατανοήσεις λιστών.

Τέλος, θα συνεχίσετε να χρησιμοποιείτε το NumPy και τις ενσωματωμένες συναρτήσεις του για να εκτελέσετε τον πολλαπλασιασμό πίνακα πιο αποτελεσματικά.

Πώς να ελέγξετε εάν ο πολλαπλασιασμός πίνακα είναι έγκυρος

Πριν γράψουμε κώδικα Python για πολλαπλασιασμό πίνακα, ας επανεξετάσουμε τα βασικά του πολλαπλασιασμού μήτρας.

Ο πολλαπλασιασμός πίνακα μεταξύ δύο πινάκων Α και Β είναι έγκυρος μόνο εάν ο αριθμός των στηλών στον πίνακα Α είναι ίσος με τον αριθμό των γραμμών στον πίνακα Β.

Πιθανότατα θα είχατε συναντήσει αυτήν την συνθήκη για τον πολλαπλασιασμό του πίνακα πριν. Ωστόσο, έχετε αναρωτηθεί ποτέ γιατί συμβαίνει αυτό;

Λοιπόν, οφείλεται στον τρόπο με τον οποίο λειτουργεί ο πολλαπλασιασμός του πίνακα. Ρίξτε μια ματιά στην παρακάτω εικόνα.

Στο γενικό μας παράδειγμα, ο πίνακας Α έχει m γραμμές και n στήλες. Και ο πίνακας Β έχει n γραμμές και p στήλες.

Ποιο είναι το σχήμα του πίνακα προϊόντος;

Το στοιχείο στον δείκτη (i, j) στον προκύπτον πίνακα C είναι το γινόμενο κουκίδων της σειράς i του πίνακα A και της στήλης j του πίνακα B.

Έτσι, για να λάβετε ένα στοιχείο σε έναν συγκεκριμένο δείκτη στον προκύπτον πίνακα C, θα πρέπει να υπολογίσετε το γινόμενο κουκίδων της αντίστοιχης γραμμής και στήλης στους πίνακες Α και Β, αντίστοιχα.

Επαναλαμβάνοντας την παραπάνω διαδικασία, θα λάβετε τον πίνακα προϊόντος C του σχήματος mxp—με m γραμμές και στήλες p, όπως φαίνεται παρακάτω.

Και το γινόμενο με τελείες ή το εσωτερικό γινόμενο μεταξύ δύο διανυσμάτων a και b δίνεται από την ακόλουθη εξίσωση.

Ας συνοψίσουμε τώρα:

  • Είναι προφανές ότι το γινόμενο κουκίδων ορίζεται μόνο μεταξύ διανυσμάτων ίσου μήκους.
  • Έτσι, για να είναι έγκυρο το γινόμενο με τελείες μεταξύ μιας γραμμής και μιας στήλης – όταν πολλαπλασιάζετε δύο πίνακες – θα χρειαστείτε να έχουν και οι δύο τον ίδιο αριθμό στοιχείων.
  • Στο παραπάνω γενικό παράδειγμα, κάθε γραμμή στον πίνακα Α έχει n στοιχεία. Και κάθε στήλη στον πίνακα Β έχει επίσης n στοιχεία.

Εάν ρίξετε μια πιο προσεκτική ματιά, το n είναι ο αριθμός των στηλών στον πίνακα Α και είναι επίσης ο αριθμός των σειρών στον πίνακα Β. Και αυτός είναι ακριβώς ο λόγος για τον οποίο χρειάζεστε ο αριθμός των στηλών στον πίνακα Α να είναι ίσος με τον αριθμό σειρών στον πίνακα Β.

  Πώς να λάβετε επιστροφή χρημάτων στο Amazon

Ελπίζω να καταλαβαίνετε την προϋπόθεση για να είναι έγκυρος ο πολλαπλασιασμός πίνακα και πώς να αποκτήσετε κάθε στοιχείο στον πίνακα γινομένων.

Ας προχωρήσουμε στη σύνταξη κώδικα Python για να πολλαπλασιάσουμε δύο πίνακες.

Γράψτε μια προσαρμοσμένη συνάρτηση Python για να πολλαπλασιάσετε πίνακες

Ως πρώτο βήμα, ας γράψουμε μια προσαρμοσμένη συνάρτηση για τον πολλαπλασιασμό πινάκων.

Αυτή η λειτουργία πρέπει να κάνει τα εξής:

  • Αποδεχτείτε δύο πίνακες, τον Α και τον Β, ως εισόδους.
  • Ελέγξτε εάν ο πολλαπλασιασμός πίνακα μεταξύ Α και Β είναι έγκυρος.
  • Εάν ισχύει, πολλαπλασιάστε τους δύο πίνακες A και B και επιστρέψτε τον πίνακα γινομένων C.
  • Διαφορετικά, επιστρέψτε ένα μήνυμα σφάλματος ότι οι πίνακες A και B δεν μπορούν να πολλαπλασιαστούν.

Βήμα 1: Δημιουργήστε δύο πίνακες ακεραίων χρησιμοποιώντας τη συνάρτηση random.randint() του NumPy. Μπορείτε επίσης να δηλώσετε πίνακες ως ένθετες λίστες Python.

import numpy as np
np.random.seed(27)
A = np.random.randint(1,10,size = (3,3))
B = np.random.randint(1,10,size = (3,2))
print(f"Matrix A:n {A}n")
print(f"Matrix B:n {B}n")

# Output
Matrix A:
 [[4 9 9]
 [9 1 6]
 [9 2 3]]

Matrix B:
 [[2 2]
 [5 7]
 [4 4]]

Βήμα 2: Προχωρήστε και ορίστε τη συνάρτηση multiply_matrix(A,B). Αυτή η συνάρτηση λαμβάνει δύο πίνακες A και B ως εισόδους και επιστρέφει τον πίνακα γινομένων C εάν είναι έγκυρος ο πολλαπλασιασμός του πίνακα.

def multiply_matrix(A,B):
  global C
  if  A.shape[1] == B.shape[0]:
    C = np.zeros((A.shape[0],B.shape[1]),dtype = int)
    for row in range(rows): 
        for col in range(cols):
            for elt in range(len(B)):
              C[row, col] += A[row, elt] * B[elt, col]
    return C
  else:
    return "Sorry, cannot multiply A and B."

Ανάλυση του ορισμού της συνάρτησης

Ας προχωρήσουμε στην ανάλυση του ορισμού της συνάρτησης.

Δήλωση C ως καθολική μεταβλητή: Από προεπιλογή, όλες οι μεταβλητές μέσα σε μια συνάρτηση Python έχουν τοπικό εύρος. Και δεν μπορείτε να έχετε πρόσβαση σε αυτά εκτός λειτουργίας. Για να κάνουμε τον πίνακα προϊόντων C προσβάσιμο από έξω, θα πρέπει να τον δηλώσουμε ως καθολική μεταβλητή. Απλώς προσθέστε τον καθολικό προσδιορισμό πριν από το όνομα της μεταβλητής.

Ελέγξτε εάν ο πολλαπλασιασμός του πίνακα είναι έγκυρος: Χρησιμοποιήστε το χαρακτηριστικό σχήμα για να ελέγξετε εάν τα Α και Β μπορούν να πολλαπλασιαστούν. Για κάθε πίνακα arr, arr.shape[0] και αρρ.σχήμα[1] δώστε τον αριθμό των γραμμών και των στηλών, αντίστοιχα. Αν λοιπόν Α.σχήμα[1] == Β.σχήμα[0] ελέγχει εάν ο πολλαπλασιασμός του πίνακα είναι έγκυρος. Μόνο αν αυτή η συνθήκη είναι True, θα υπολογιστεί ο πίνακας προϊόντος. Διαφορετικά, η συνάρτηση επιστρέφει ένα μήνυμα σφάλματος.

Χρησιμοποιήστε ένθετους βρόχους για τον υπολογισμό των τιμών: Για να υπολογίσουμε τα στοιχεία του προκύπτοντος πίνακα, πρέπει να κάνουμε βρόχο μέσα από τις σειρές του πίνακα A και ο εξωτερικός βρόχος for κάνει αυτό. Ο εσωτερικός βρόχος for μας βοηθά να κάνουμε βρόχο μέσα από τη στήλη του πίνακα Β. Και ο πιο εσωτερικός βρόχος for βοηθά στην πρόσβαση σε κάθε στοιχείο στην επιλεγμένη στήλη.

▶️ Τώρα που μάθαμε πώς λειτουργεί η συνάρτηση Python για τον πολλαπλασιασμό πινάκων, ας καλέσουμε τη συνάρτηση με τους πίνακες A και B που δημιουργήσαμε νωρίτερα.

multiply_matrix(A,B)

# Output
array([[ 89, 107],
       [ 47,  49],
       [ 40,  44]])

Καθώς ο πολλαπλασιασμός του πίνακα μεταξύ Α και Β είναι έγκυρος, η συνάρτηση multiply_matrix() επιστρέφει τον πίνακα γινομένων C.

  Πώς να βρείτε τον κωδικό πρόσβασης διαχειριστή σε Mac

Χρησιμοποιήστε Python Nested List Comprehension για να πολλαπλασιάσετε πίνακες

Στην προηγούμενη ενότητα, γράψατε μια συνάρτηση Python για να πολλαπλασιάσετε πίνακες. Τώρα, θα δείτε πώς μπορείτε να χρησιμοποιήσετε τις κατανοήσεις ένθετων λιστών για να κάνετε το ίδιο.

Εδώ είναι η κατανόηση ένθετης λίστας για τον πολλαπλασιασμό πινάκων.

Στην αρχή, αυτό μπορεί να φαίνεται περίπλοκο. Αλλά θα αναλύσουμε την κατανόηση της ένθετης λίστας βήμα προς βήμα.

Ας εστιάσουμε στην κατανόηση μιας λίστας κάθε φορά και ας προσδιορίσουμε τι κάνει.

Θα χρησιμοποιήσουμε το ακόλουθο γενικό πρότυπο για την κατανόηση της λίστας:

[<do-this> for <item> in <iterable>]

where,
<do-this>: what you'd like to do—expression or operation
<item>: each item you'd like to perform the operation on
<iterable>: the iterable (list, tuple, etc.) that you're looping through

▶️ Ρίξτε μια ματιά στον οδηγό μας Κατανόηση λίστας στην Python – με Παραδείγματα για να κατανοήσετε σε βάθος.

Πριν προχωρήσετε, σημειώστε ότι θα θέλαμε να δημιουργήσουμε τον προκύπτοντα πίνακα C μία σειρά τη φορά.

Επεξήγηση της κατανόησης ένθετης λίστας

Βήμα 1: Υπολογίστε μια μεμονωμένη τιμή στον πίνακα C

Δεδομένης της σειράς i του πίνακα A και της στήλης j του πίνακα B, η παρακάτω έκφραση δίνει την καταχώρηση στο δείκτη (i, j) στον πίνακα C.

sum(a*b for a,b in zip(A_row, B_col)

# zip(A_row, B_col) returns an iterator of tuples
# If A_row = [a1, a2, a3] & B_col = [b1, b2, b3]
# zip(A_row, B_col) returns (a1, b1), (a2, b2), and so on

Εάν i = j = 1, η παράσταση θα επιστρέψει την καταχώρηση c_11 του πίνακα C. Έτσι, μπορείτε να πάρετε ένα στοιχείο σε μία σειρά με αυτόν τον τρόπο.

Βήμα 2: Δημιουργήστε μια σειρά στον πίνακα C

Ο επόμενος στόχος μας είναι να φτιάξουμε μια ολόκληρη σειρά.

Για τη σειρά 1 στον πίνακα Α, πρέπει να κάνετε κύκλο σε όλες τις στήλες του πίνακα Β για να λάβετε μια πλήρη σειρά στον πίνακα C.

Επιστρέψτε στο πρότυπο κατανόησης λίστας.

  • Αντικαταστήστε το με την έκφραση από το βήμα 1, γιατί αυτό θέλετε να κάνετε.
  • Στη συνέχεια, αντικαταστήστε το με B_col—κάθε στήλη στον πίνακα Β.
  • Τέλος, αντικαταστήστε το με zip(*B)—τη λίστα που περιέχει όλες τις στήλες στον πίνακα Β.

Και εδώ είναι η πρώτη κατανόηση της λίστας.

[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 

# zip(*B): * is the unzipping operator
# zip(*B) returns a list of columns in matrix B

Βήμα 3: Δημιουργήστε όλες τις σειρές και αποκτήστε τον πίνακα C

Στη συνέχεια, θα πρέπει να συμπληρώσετε τον πίνακα προϊόντος C υπολογίζοντας τις υπόλοιπες σειρές.

Και για αυτό, πρέπει να κάνετε κύκλο σε όλες τις σειρές στον πίνακα A.

Επιστρέψτε ξανά στην κατανόηση της λίστας και κάντε τα εξής.

  • Αντικαταστήστε το με την κατανόηση λίστας από το βήμα 2. Θυμηθείτε ότι υπολογίσαμε μια ολόκληρη σειρά στο προηγούμενο βήμα.
  • Τώρα, αντικαταστήστε το με A_row—κάθε σειρά στον πίνακα A.
  • Και το σας είναι ο ίδιος ο πίνακας A, καθώς περιηγείστε στις σειρές του.

Και εδώ είναι η τελική κατανόηση της ένθετης λίστας μας.🎊

[[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 
    for A_row in A]

Ήρθε η ώρα να επαληθεύσετε το αποτέλεσμα! ✔

# cast into <a href="https://grtechpc.org.com/numpy-reshape-arrays-in-python/">NumPy array</a> using np.array()
C = np.array([[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] 
    for A_row in A])

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Αν ρίξετε μια πιο προσεκτική ματιά, αυτό ισοδυναμεί με τους ένθετους βρόχους for που είχαμε νωρίτερα—απλώς είναι πιο συνοπτικός.

Μπορείτε επίσης να το κάνετε αυτό ακόμα πιο αποτελεσματικά χρησιμοποιώντας ορισμένες ενσωματωμένες λειτουργίες. Ας μάθουμε για αυτά στην επόμενη ενότητα.

Χρησιμοποιήστε τη NumPy matmul() για να πολλαπλασιάσετε πίνακες στην Python

Η np.matmul() λαμβάνει δύο πίνακες ως είσοδο και επιστρέφει το γινόμενο εάν ο πολλαπλασιασμός του πίνακα μεταξύ των πινάκων εισόδου είναι έγκυρος.

C = np.matmul(A,B)
print(C)

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Παρατηρήστε πώς αυτή η μέθοδος είναι απλούστερη από τις δύο μεθόδους που μάθαμε νωρίτερα. Στην πραγματικότητα, αντί για np.matmul(), μπορείτε να χρησιμοποιήσετε έναν ισοδύναμο τελεστή @ και θα το δούμε αμέσως.

Πώς να χρησιμοποιήσετε το @ Operator στην Python για να πολλαπλασιάσετε πίνακες

Στην Python, ο @ είναι ένας δυαδικός τελεστής που χρησιμοποιείται για τον πολλαπλασιασμό του πίνακα.

Λειτουργεί σε δύο πίνακες, και γενικά, σε πίνακες N-διάστατων NumPy και επιστρέφει τον πίνακα προϊόντος.

Σημείωση: Πρέπει να έχετε Python 3.5 και νεότερη έκδοση για να χρησιμοποιήσετε τον τελεστή @.

Δείτε πώς μπορείτε να το χρησιμοποιήσετε.

C = [email protected]
print(C)

# Output
array([[ 89, 107],
       [ 47,  49],
       [ 40,  44]])

Παρατηρήστε ότι ο πίνακας γινομένων C είναι ο ίδιος με αυτόν που λάβαμε νωρίτερα.

Μπορείτε να χρησιμοποιήσετε το np.dot() για να πολλαπλασιάσετε πίνακες;

Αν έχετε συναντήσει ποτέ κώδικα που χρησιμοποιεί np.dot() για να πολλαπλασιάζει δύο πίνακες, δείτε πώς λειτουργεί.

C = np.dot(A,B)
print(C)

# Output:
[[ 89 107]
 [ 47  49]
 [ 40  44]]

Θα δείτε ότι το np.dot(A, B) επιστρέφει επίσης τον αναμενόμενο πίνακα προϊόντος.

Ωστόσο, σύμφωνα με Έγγραφα NumPyθα πρέπει να χρησιμοποιήσετε το np.dot() μόνο για να υπολογίσετε το γινόμενο κουκίδων δύο μονοδιάστατων διανυσμάτων και όχι για τον πολλαπλασιασμό πίνακα.

Θυμηθείτε από την προηγούμενη ενότητα, το στοιχείο στον δείκτη (i, j) του πίνακα γινομένων C είναι το γινόμενο κουκίδων της σειράς i του πίνακα A και της στήλης j του πίνακα B.

Καθώς το NumPy μεταδίδει σιωπηρά αυτήν τη λειτουργία προϊόντος με κουκκίδες σε όλες τις σειρές και όλες τις στήλες, λαμβάνετε τον προκύπτοντα πίνακα προϊόντος. Αλλά για να διατηρήσετε τον κώδικά σας ευανάγνωστο και να αποφύγετε την ασάφεια, χρησιμοποιήστε το np.matmul() ή τον τελεστή @.

συμπέρασμα

🎯 Σε αυτό το σεμινάριο, μάθατε τα εξής.

  • Προϋπόθεση για να είναι έγκυρος ο πολλαπλασιασμός του πίνακα: αριθμός στηλών στον πίνακα A = αριθμός σειρών στον πίνακα B.
  • Πώς να γράψετε μια προσαρμοσμένη συνάρτηση Python που ελέγχει εάν ο πολλαπλασιασμός πίνακα είναι έγκυρος και επιστρέφει τον πίνακα προϊόντος. Το σώμα της συνάρτησης χρησιμοποιεί ένθετα για βρόχους.
  • Στη συνέχεια, μάθατε πώς να χρησιμοποιείτε τις κατανοήσεις ένθετων λιστών για να πολλαπλασιάζετε πίνακες. Είναι πιο συνοπτικά από ό,τι για βρόχους, αλλά είναι επιρρεπείς σε προβλήματα αναγνωσιμότητας.
  • Τέλος, μάθατε να χρησιμοποιείτε την ενσωματωμένη συνάρτηση NumPy np.matmul() για να πολλαπλασιάσετε πίνακες και πώς αυτή είναι η πιο αποτελεσματική από την άποψη της ταχύτητας.
  • Μάθατε επίσης για τον τελεστή @ για τον πολλαπλασιασμό δύο πινάκων στην Python.

Και αυτό ολοκληρώνει τη συζήτησή μας για τον πολλαπλασιασμό μήτρας στην Python. Ως επόμενο βήμα, μάθετε πώς να ελέγχετε εάν ένας αριθμός είναι πρώτος στην Python. Ή λύστε ενδιαφέροντα προβλήματα σε συμβολοσειρές Python.

Καλή μάθηση!🎉