La notació de suma d'Einstein és una manera concisa i potent de representar les operacions de tensor, que s'utilitza sovint en física i aprenentatge automàtic. Ens permet escriure càlculs complexos sobre tensors de forma compacta. Cobrirem els conceptes bàsics sobre la suma d'Einstein, com utilitzar-lo a Python amb Numpy i Tensorflow, i donarem exemples per il·lustrar-ne l'ús.
Conceptes bàsics de la suma d'Einstein
La notació de suma d'Einstein (Einsum) es basa en la idea de sumar sobre índexs repetits en expressions tensorials. Es basa en les dues regles següents:
1. Suma sobre índexs repetits: si un índex apareix dues vegades en un terme, es suma sobre
2. Índexs lliures: Els índexs que apareixen només una vegada són índexs lliures i representen els eixos del tensor de sortida
Il·lustrem-ho amb l'exemple de multiplicar dues matrius A i B: la matriu C resultant es defineix com
A Python, tant les biblioteques Numpy com Tensorflow proporcionen una funció 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]]
A l'exemple anterior, ij,jk->ik
és la cadena einsum:
"ij" representa els índexs de la matriu A
jk
representa els índexs de la matriu B
->ik
especifica els índexs de la matriu de sortida C
L'operació suma sobre l'índex j
Semblaria el mateix codi a Tensorflow
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)
Més exemples
Producte interior dels vectors
El producte interior (producte puntual) de dos vectors a i b es defineix com
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.einsum('i,i->', a, b)
print(c) # Output: 32
Producte exterior dels vectors
El producte exterior de dos vectors a i b ve donat per:
C = np.einsum('i,j->ij', a, b)
print(C)
# Output
# [[4 5 6]
# [8 10 12]
# [12 15 18]]
Transposició d'una matriu
La transposició d'una matriu A es pot obtenir canviant els seus índexs
A_transpose = np.einsum('ij->ji', A)
print(A_transpose)
# Output
# [[1. 3.]
# [2. 4.]]
Traça d'una matriu
La traça d'una matriu A és la suma dels seus elements diagonals:
trace = np.einsum('ii->', A)
print(trace)
# Output: 5.0
Multiplicació de matrius per lots
Einsum és especialment útil per a operacions per lots. Suposem que tenim un lot de matrius A i B i volem multiplicar les matrius corresponents al 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)
Aquí, "b" representa la dimensió del lot.
Avantatges de la notació Einsum
1. Concisió: La notació Einsum és compacta i pot representar operacions complexes de manera succinta
2. Flexibilitat: pot gestionar una gran varietat d'operacions de tensor sense remodelar o transposar matrius explícitament
3. Eficiència: Moltes biblioteques optimitzen les operacions d'einsum internament, la qual cosa pot conduir a un millor rendiment.