3 façons de multiplier les matrices en Python
Dans ce guide, nous allons explorer la manière de multiplier deux matrices en utilisant Python.
Nous débuterons par l'étude de la condition nécessaire pour que la multiplication matricielle soit possible, et nous écrirons une fonction Python personnalisée pour effectuer cette opération. Ensuite, nous verrons comment reproduire ce résultat en utilisant des listes imbriquées.
Enfin, nous verrons comment employer NumPy et ses fonctions intégrées pour réaliser la multiplication matricielle de manière plus efficace.
Comment vérifier la validité de la multiplication matricielle
Avant de nous lancer dans le codage Python pour la multiplication matricielle, récapitulons les principes fondamentaux de cette opération.
La multiplication de deux matrices, A et B, est possible seulement si le nombre de colonnes de la matrice A est égal au nombre de lignes de la matrice B.
Cette condition de validité pour la multiplication matricielle est probablement familière. Toutefois, vous êtes-vous déjà demandé pourquoi cette condition est indispensable ?
Cela découle directement du fonctionnement de la multiplication matricielle. L'image ci-dessous en fournit une illustration.
Dans cet exemple générique, la matrice A possède m lignes et n colonnes, tandis que la matrice B possède n lignes et p colonnes.
Quelle est la dimension de la matrice résultante ?
L'élément situé à la position (i, j) dans la matrice résultante C est le produit scalaire de la ligne i de la matrice A et de la colonne j de la matrice B.
Ainsi, pour calculer un élément précis de la matrice résultante C, il est nécessaire de calculer le produit scalaire entre la ligne et la colonne correspondantes des matrices A et B, respectivement.
En répétant cette opération, on obtient la matrice produit C de dimension m x p, avec m lignes et p colonnes, comme illustré ci-dessous.

Le produit scalaire (ou produit interne) entre deux vecteurs a et b est défini par l'équation suivante :

Récapitulons maintenant les points essentiels :
- Le produit scalaire est uniquement défini entre des vecteurs de même longueur.
- Par conséquent, pour que le produit scalaire entre une ligne et une colonne soit possible lors de la multiplication matricielle, ces deux entités doivent comporter le même nombre d'éléments.
- Dans l'exemple générique mentionné ci-dessus, chaque ligne de la matrice A comporte n éléments, et chaque colonne de la matrice B en possède également n.
En y regardant de plus près, n représente à la fois le nombre de colonnes de la matrice A et le nombre de lignes de la matrice B. C'est précisément la raison pour laquelle il est impératif que le nombre de colonnes de la matrice A corresponde au nombre de lignes de la matrice B.
J'espère que vous comprenez maintenant la condition nécessaire à la validité de la multiplication matricielle et comment obtenir chaque élément de la matrice résultante.
Passons maintenant à la création de code Python pour multiplier deux matrices.
Écrire une fonction Python personnalisée pour la multiplication de matrices
Commençons par développer une fonction personnalisée capable de multiplier des matrices.
Cette fonction doit accomplir les tâches suivantes :
- Accepter deux matrices, A et B, en tant qu'arguments d'entrée.
- Vérifier si la multiplication matricielle entre A et B est valide.
- Si elle est valide, multiplier les matrices A et B, et renvoyer la matrice résultat C.
- Dans le cas contraire, renvoyer un message d'erreur indiquant que les matrices A et B ne peuvent pas être multipliées.
Étape 1 : Créer deux matrices d'entiers en utilisant la fonction `random.randint()` de NumPy. Vous pouvez aussi initialiser les matrices en tant que listes Python imbriquées.
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"Matrice A:n {A}n")
print(f"Matrice B:n {B}n")
# Résultat
Matrice A:
[[4 9 9]
[9 1 6]
[9 2 3]]
Matrice B:
[[2 2]
[5 7]
[4 4]]
Étape 2 : Définissons la fonction `multiplier_matrix(A,B)`. Cette fonction prend en argument deux matrices A et B, et retourne la matrice résultante C si la multiplication matricielle est réalisable.
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(A.shape[0]):
for col in range(B.shape[1]):
for elt in range(A.shape[1]):
C[row, col] += A[row, elt] * B[elt, col]
return C
else:
return "La multiplication des matrices A et B est impossible."
Analyse de la fonction
Examinons en détail la définition de cette fonction.
Déclaration de C comme variable globale : par défaut, toutes les variables déclarées à l'intérieur d'une fonction Python ont une portée locale. Il est impossible d'y accéder depuis l'extérieur de la fonction. Pour rendre la matrice résultante C accessible en dehors de la fonction, il faut la déclarer comme variable globale. Il suffit d'ajouter le mot-clé `global` devant le nom de la variable.
Vérification de la validité de la multiplication matricielle : utiliser l'attribut `shape` pour vérifier si A et B peuvent être multipliées. Pour toute matrice `arr`, `arr.shape[0]` et `arr.shape[1]` fournissent respectivement le nombre de lignes et de colonnes. Ainsi, la condition `A.shape[1] == B.shape[0]` vérifie si la multiplication matricielle est valide. La matrice résultat n'est calculée que si cette condition est satisfaite. Dans le cas contraire, la fonction retourne un message d'erreur.
Utilisation de boucles imbriquées pour le calcul des valeurs : pour obtenir les éléments de la matrice résultante, il faut parcourir les lignes de la matrice A, ce que fait la boucle `for` externe. La boucle `for` interne sert à parcourir les colonnes de la matrice B. La boucle `for` la plus interne permet d'accéder à chaque élément de la colonne sélectionnée.
▶️ Maintenant que nous avons compris comment fonctionne la fonction Python pour multiplier les matrices, invoquons cette fonction avec les matrices A et B que nous avons générées précédemment.
multiply_matrix(A,B)
# Résultat
array([[ 89, 107],
[ 47, 49],
[ 40, 44]])
Comme la multiplication matricielle entre A et B est possible, la fonction `multiplier_matrix()` renvoie la matrice résultat C.
Utilisation de la compréhension de liste imbriquée pour la multiplication matricielle en Python
Dans la section précédente, nous avons créé une fonction Python pour la multiplication matricielle. Nous allons maintenant explorer comment utiliser les compréhensions de liste imbriquées pour accomplir cette même tâche.
Voici la compréhension de liste imbriquée pour la multiplication de matrices.

Cette expression peut sembler compliquée au premier abord. Nous allons la décortiquer étape par étape.
Concentrons-nous sur une compréhension de liste à la fois pour en identifier le rôle.
Nous utiliserons le modèle général suivant pour la compréhension de liste :
[<action> for <élément> in <itérable>] où, <action>: l'action à réaliser, l'expression ou l'opération <élément>: chaque élément sur lequel l'opération doit être effectuée <itérable>: la collection itérable (liste, tuple, etc.) sur laquelle on boucle
▶️ Consultez notre guide sur la compréhension de liste en Python pour une compréhension approfondie de ce concept.
Avant de continuer, il est important de noter que notre objectif est de construire la matrice résultante C ligne par ligne.
Explication de la compréhension de liste imbriquée
Étape 1 : Calculer une seule valeur dans la matrice C
Étant donné la ligne `i` de la matrice A et la colonne `j` de la matrice B, l'expression suivante fournit l'élément situé à la position `(i, j)` dans la matrice C.
sum(a*b for a,b in zip(A_row, B_col)) # zip(A_row, B_col) retourne un itérateur de tuples # Si A_row = [a1, a2, a3] et B_col = [b1, b2, b3] # zip(A_row, B_col) retourne (a1, b1), (a2, b2), etc.
Si `i = j = 1`, l'expression renverra l'élément `c_11` de la matrice C. Il est donc possible d'obtenir un élément dans une ligne de cette manière.
Étape 2 : Construire une ligne de la matrice C
Notre objectif suivant est de construire une ligne complète.
Pour la ligne 1 de la matrice A, il est nécessaire de parcourir toutes les colonnes de la matrice B pour obtenir une ligne complète de la matrice C.
Revenons au modèle de compréhension de liste.
- Remplacer <action> par l'expression de l'étape 1, car c'est cette action que nous souhaitons réaliser.
- Remplacer <élément> par `B_col`, chaque colonne de la matrice B.
- Enfin, remplacer <itérable> par `zip(*B)`, la liste contenant toutes les colonnes de la matrice B.
Voici la première compréhension de liste :
[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)] # zip(*B) : * est l'opérateur de décompression # zip(*B) retourne une liste des colonnes de la matrice B
Étape 3 : Construire toutes les lignes et obtenir la matrice C
Il faut ensuite remplir la matrice résultat C en calculant le reste des lignes.
Pour cela, il est nécessaire de parcourir toutes les lignes de la matrice A.
Revenons encore une fois à la compréhension de liste, et procédons de la manière suivante :
- Remplacer <action> par la compréhension de liste de l'étape 2. Rappelez-vous que nous avons calculé une ligne complète à l'étape précédente.
- Remplacer <élément> par `A_row`, chaque ligne de la matrice A.
- L'élément <itérable> est la matrice A elle-même, lorsque nous parcourons ses lignes.
Voici notre compréhension de liste imbriquée finale. 🎉
[[sum(a*b for a,b in zip(A_row, B_col)) for B_col in zip(*B)]
for A_row in A]
Il est temps de vérifier le résultat ! ✔
# conversion en tableau NumPy avec 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])
# Résultat :
[[ 89 107]
[ 47 49]
[ 40 44]]
En y regardant de plus près, cette expression est équivalente aux boucles `for` imbriquées que nous avons utilisées précédemment, mais elle est beaucoup plus concise.
Il est également possible de réaliser cette opération de manière plus efficace en utilisant certaines fonctions intégrées. Découvrons-les dans la section suivante.
Utilisation de NumPy `matmul()` pour la multiplication de matrices en Python
La fonction `np.matmul()` prend deux matrices en argument et retourne le produit si la multiplication matricielle entre les matrices d'entrée est valide.
C = np.matmul(A,B) print(C) # Résultat : [[ 89 107] [ 47 49] [ 40 44]]
Remarquez la simplicité de cette méthode par rapport aux deux méthodes précédemment abordées. En fait, il est possible de remplacer `np.matmul()` par l'opérateur `@`, ce que nous allons voir tout de suite.
Comment utiliser l'opérateur `@` pour la multiplication de matrices en Python
En Python, l'opérateur `@` est un opérateur binaire utilisé pour la multiplication matricielle.
Il prend deux matrices en argument (ou plus généralement des tableaux NumPy à N dimensions) et retourne la matrice résultante.
Remarque : il est nécessaire d'utiliser Python 3.5 ou une version ultérieure pour utiliser l'opérateur `@`.
Voici un exemple d'utilisation :
C = A @ B
print(C)
# Résultat
array([[ 89, 107],
[ 47, 49],
[ 40, 44]])
On constate que la matrice résultat C est identique à celle que nous avons obtenue précédemment.
Peut-on utiliser `np.dot()` pour la multiplication de matrices ?
Si vous avez déjà rencontré du code utilisant `np.dot()` pour multiplier deux matrices, voici comment cela fonctionne.
C = np.dot(A,B) print(C) # Résultat : [[ 89 107] [ 47 49] [ 40 44]]
Vous constatez que `np.dot(A, B)` retourne également la matrice résultat attendue.
Cependant, d'après la documentation NumPy, il est préférable de n'utiliser `np.dot()` que pour calculer le produit scalaire de deux vecteurs unidimensionnels, et non pour la multiplication matricielle.
Rappelons que, comme mentionné précédemment, l'élément situé à la position `(i, j)` de la matrice résultat C est le produit scalaire de la ligne `i` de la matrice A et de la colonne `j` de la matrice B.
Comme NumPy diffuse implicitement cette opération de produit scalaire sur l'ensemble des lignes et colonnes, vous obtenez bien la matrice résultat. Cependant, pour plus de clarté et afin d'éviter toute ambiguïté, il est recommandé d'utiliser plutôt `np.matmul()` ou l'opérateur `@`.
Conclusion
🎯 Dans ce tutoriel, nous avons exploré les points suivants :
- La condition de validité pour la multiplication matricielle : le nombre de colonnes de la matrice A doit être égal au nombre de lignes de la matrice B.
- Comment développer une fonction Python personnalisée pour vérifier si la multiplication matricielle est possible et renvoyer la matrice résultat. Le cœur de cette fonction utilise des boucles `for` imbriquées.
- Ensuite, nous avons vu comment utiliser des listes imbriquées pour la multiplication de matrices. Cette méthode est plus concise que les boucles `for`, mais peut être moins lisible.
- Enfin, nous avons appris à utiliser la fonction intégrée NumPy `np.matmul()` pour la multiplication de matrices et pourquoi cette approche est la plus efficace en termes de performance.
- Nous avons également découvert l'opérateur `@` pour la multiplication de deux matrices en Python.
Ceci termine notre discussion sur la multiplication matricielle en Python. Pour aller plus loin, vous pouvez étudier comment vérifier si un nombre est premier en Python, ou encore explorer des problèmes intéressants liés aux chaînes de caractères Python.
Bon apprentissage ! 🎉