Opérations avancées avec Einsum
Maintenant que nous sommes à l'aise avec les opérations de base de einsum
, explorons quelques applications plus avancées. Ces opérations démontrent le véritable pouvoir et la flexibilité de la fonction einsum
.
Extraire les éléments diagonaux d'une matrice est une opération courante en algèbre linéaire. Pour une matrice A, ses éléments diagonaux forment un vecteur d tel que :
d_i = A_{ii}
Voici comment extraire la diagonale à l'aide de einsum
:
## Create a random square matrix
A = np.random.rand(4, 4)
print("Matrix A:")
print(A)
## Extract diagonal using einsum
diagonal = np.einsum('ii->i', A)
print("\nDiagonal elements using einsum:")
print(diagonal)
## Verify with NumPy's diagonal function
numpy_diagonal = np.diagonal(A)
print("\nDiagonal elements using np.diagonal():")
print(numpy_diagonal)
La notation 'ii->i'
signifie :
ii
représente l'indice répété pour les éléments diagonaux de A
i
signifie que nous extrayons ces éléments dans un tableau 1D
Trace d'une matrice
La trace d'une matrice est la somme de ses éléments diagonaux. Pour une matrice A, sa trace est :
\text{trace}(A) = \sum_i A_{ii}
Voici comment calculer la trace à l'aide de einsum
:
## Using the same matrix A from above
trace = np.einsum('ii->', A)
print("Trace of matrix A using einsum:", trace)
## Verify with NumPy's trace function
numpy_trace = np.trace(A)
print("Trace of matrix A using np.trace():", numpy_trace)
La notation 'ii->'
signifie :
ii
représente l'indice répété pour les éléments diagonaux
- L'indice de sortie vide signifie que nous sommons tous les éléments diagonaux pour obtenir un scalaire
Multiplication par lots de matrices
einsum
s'avère particulièrement utile lorsqu'il s'agit d'effectuer des opérations sur des tableaux de dimensions supérieures. Par exemple, la multiplication par lots de matrices consiste à multiplier des paires de matrices de deux lots.
Si nous avons un lot de matrices A de forme (n, m, p) et un lot de matrices B de forme (n, p, q), la multiplication par lots de matrices nous donne un résultat C de forme (n, m, q) :
C_{ijk} = \sum_l A_{ijl} \times B_{ilk}
Voici comment effectuer la multiplication par lots de matrices à l'aide de einsum
:
## Create batches of matrices
n, m, p, q = 5, 3, 4, 2 ## Batch size and matrix dimensions
A = np.random.rand(n, m, p) ## Batch of 5 matrices, each 3x4
B = np.random.rand(n, p, q) ## Batch of 5 matrices, each 4x2
print("Shape of batch A:", A.shape)
print("Shape of batch B:", B.shape)
## Batch matrix multiplication using einsum
C = np.einsum('nmp,npq->nmq', A, B)
print("\nShape of result batch C:", C.shape) ## Should be (5, 3, 2)
## Let's check the first matrix multiplication in the batch
print("\nFirst result matrix from batch using einsum:")
print(C[0])
## Verify with NumPy's matmul function
numpy_batch_matmul = np.matmul(A, B)
print("\nFirst result matrix from batch using np.matmul:")
print(numpy_batch_matmul[0])
La notation 'nmp,npq->nmq'
signifie :
nmp
représente les indices du lot A (n pour le lot, m pour les lignes, p pour les colonnes)
npq
représente les indices du lot B (n pour le lot, p pour les lignes, q pour les colonnes)
nmq
représente les indices du lot de sortie C (n pour le lot, m pour les lignes, q pour les colonnes)
- L'indice répété
p
est sommés (multiplication de matrices)
Pourquoi utiliser Einsum ?
Vous vous demandez peut-être pourquoi nous devrions utiliser einsum
alors que NumPy propose déjà des fonctions spécialisées pour ces opérations. Voici quelques avantages :
- Interface unifiée :
einsum
offre une seule fonction pour de nombreuses opérations sur les tableaux
- Flexibilité : Elle peut exprimer des opérations qui nécessiteraient autrement plusieurs étapes
- Lisibilité : Une fois que vous comprenez la notation, le code devient plus concis
- Performances : Dans de nombreux cas, les opérations
einsum
sont optimisées et efficaces
Pour les opérations tensorielle complexes, einsum
offre souvent la mise en œuvre la plus claire et la plus directe.