La notation Einstein Summation est un moyen concis et puissant de représenter les opérations tensorielles, souvent utilisée en physique et en apprentissage automatique. Cela nous permet d'écrire des calculs complexes sur des tenseurs sous une forme compacte. Nous aborderons les bases de la sommation Einstein, comment l'utiliser en Python avec Numpy et Tensorflow, et fournirons des exemples pour illustrer son utilisation.
Bases de la sommation d'Einstein
La notation de sommation d'Einstein (Einsum) est basée sur l'idée de additionner des indices répétés dans des expressions tensorielles. Elle repose sur les deux règles suivantes :
1. Somme sur indices répétés : Si un indice apparaît deux fois dans un terme, il est additionné sur
2. Indices libres : Les indices qui n'apparaissent qu'une seule fois sont des indices libres et représentent les axes du tenseur de sortie
Illustrons cela avec l'exemple de la multiplication de deux matrices A et B : la matrice résultante C est définie comme
En Python, les bibliothèques Numpy et Tensorflow fournissent une fonction einsum.
Numpy
import numpy as np
# Define two matrices A and B
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
# Perform matrix multiplication using einsum
C = np.einsum('ij,jk->ik', A, B)
print(C)
# [[19 22]
# [43 50]]
Dans l'exemple ci-dessus, ij,jk->ik
est la chaîne einsum :
ij
représente les indices de la matrice A
jk
représente les indices de la matrice B
->ik
spécifie les indices de la matrice de sortie C
L'opération totalise sur l'indice j
Le même code dans Tensorflow ressemblerait à
import tensorflow as tf
# Define two matrices A and B
A = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
B = tf.constant([[5, 6], [7, 8]], dtype=tf.float32)
# Perform matrix multiplication using einsum
C = tf.einsum('ij,jk->ik', A, B)
print(C)
# tf.Tensor(
# [[19. 22.]
# [43. 50.]], shape=(2, 2), dtype=float32)
Plus d'exemples
Produit interne des vecteurs
Le produit scalaire (produit scalaire) de deux vecteurs a et b est défini comme
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.einsum('i,i->', a, b)
print(c) # Output: 32
Produit externe des vecteurs
Le produit extérieur de deux vecteurs a et b est donné par :
C = np.einsum('i,j->ij', a, b)
print(C)
# Output
# [[4 5 6]
# [8 10 12]
# [12 15 18]]
Transposition d'une matrice
La transposée d'une matrice A peut être obtenue en échangeant ses indices
A_transpose = np.einsum('ij->ji', A)
print(A_transpose)
# Output
# [[1. 3.]
# [2. 4.]]
Trace d'une Matrice
La trace d'une matrice A est la somme de ses éléments diagonaux :
trace = np.einsum('ii->', A)
print(trace)
# Output: 5.0
Multiplication de matrice par lots
Einsum est particulièrement utile pour les opérations par lots. Supposons que nous ayons un lot de matrices A et B et que nous souhaitions multiplier les matrices correspondantes dans le lot :
A = np.random.rand(3, 2, 2)
B = np.random.rand(3, 2, 2)
# Perform batch matrix multiplication
C = np.einsum('bij,bjk->bik', A, B)
print(C)
Ici, « b » représente la dimension du lot.
Avantages de la notation Einsum
1. Concision : La notation Einsum est compacte et peut représenter succinctement des opérations complexes.
2. Flexibilité : Il peut gérer une grande variété d'opérations tensorielles sans remodeler ou transposer explicitement les tableaux.
3. Efficacité : De nombreuses bibliothèques optimisent les opérations einsum en interne, conduisant potentiellement à de meilleures performances.