De Einstein Sommatie-notatie is een beknopte en krachtige manier om tensorbewerkingen weer te geven, die vaak wordt gebruikt in de natuurkunde en machinaal leren. Het stelt ons in staat complexe berekeningen op tensoren in een compacte vorm te schrijven. We behandelen de basisprincipes van Einstein-sommatie, hoe je deze kunt gebruiken in Python met Numpy en Tensorflow, en geven voorbeelden om het gebruik ervan te illustreren.
Basisprincipes van Einstein-sommatie
De Einstein Sommatie-notatie (Einsum) is gebaseerd op het idee van het optellen van herhaalde indices in tensoruitdrukkingen. Het is gebaseerd op de volgende twee regels:
1. Optelling over herhaalde indexen: Als een index twee keer voorkomt in een term, wordt deze opgeteld
2. Vrije indices: Indices die slechts één keer voorkomen, zijn vrije indices en vertegenwoordigen de assen van de uitgangstensor
Laten we dit illustreren met het voorbeeld van het vermenigvuldigen van twee matrices A en B: de resulterende matrix C wordt gedefinieerd als
In Python bieden zowel de Numpy- als de Tensorflow-bibliotheken een einsum-functie.
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]]
In het bovenstaande voorbeeld is ij,jk->ik
de einsum-tekenreeks:
ij
vertegenwoordigt de indices van matrix A
jk
vertegenwoordigt de indices van matrix B
->ik
specificeert de indices van de uitvoermatrix C
De bewerking telt op over de index j
Dezelfde code in Tensorflow zou eruit zien
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)
Meer voorbeelden
Inwendig product van vectoren
Het inproduct (puntproduct) van twee vectoren a en b wordt gedefinieerd als
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.einsum('i,i->', a, b)
print(c) # Output: 32
Uiterlijk product van vectoren
Het buitenste product van twee vectoren a en b wordt gegeven door:
C = np.einsum('i,j->ij', a, b)
print(C)
# Output
# [[4 5 6]
# [8 10 12]
# [12 15 18]]
Transponeren van een matrix
De transponering van een matrix A kan worden verkregen door de indices ervan te verwisselen
A_transpose = np.einsum('ij->ji', A)
print(A_transpose)
# Output
# [[1. 3.]
# [2. 4.]]
Spoor van een matrix
Het spoor van een matrix A is de som van zijn diagonale elementen:
trace = np.einsum('ii->', A)
print(trace)
# Output: 5.0
Batchmatrixvermenigvuldiging
Einsum is vooral handig voor batchbewerkingen. Stel dat we een batch matrices A en B hebben, en we willen de overeenkomstige matrices in de batch vermenigvuldigen:
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)
Hier vertegenwoordigt b
de batchdimensie.
Voordelen van de Einsum-notatie
1. Beknoptheid: De Einsum-notatie is compact en kan complexe bewerkingen beknopt weergeven
2. Flexibiliteit: Het kan een grote verscheidenheid aan tensorbewerkingen verwerken zonder arrays expliciet opnieuw vorm te geven of te transponeren
3. Efficiëntie: Veel bibliotheken optimaliseren de einsum-bewerkingen intern, wat mogelijk tot betere prestaties leidt.