Einstein Summation-notationen er en kortfattet og kraftfuld måde at repræsentere tensoroperationer, der ofte bruges i fysik og maskinlæring. Det giver os mulighed for at skrive komplekse beregninger på tensorer i en kompakt form. Vi vil dække det grundlæggende om Einstein-summering, hvordan man bruger det i Python med Numpy og Tensorflow, og giver eksempler til at illustrere brugen.
Grundlæggende om Einstein Summation
Einstein Summation-notationen (Einsum) er baseret på ideen om at summere over gentagne indekser i tensorudtryk. Det er baseret på følgende to regler:
1. Summation over gentagne indekser: Hvis et indeks optræder to gange i et led, summeres det over
2. Frie indekser: Indeks, der kun vises én gang, er frie indekser og repræsenterer akserne for outputtensoren
Lad os illustrere dette med eksemplet med at gange to matricer A og B: den resulterende matrix C er defineret som
I Python giver både Numpy- og Tensorflow-bibliotekerne en einsum-funktion.
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]]
I eksemplet ovenfor er ij,jk->ik
einsum-strengen:
"ij" repræsenterer indekserne for matrix A
"jk" repræsenterer indekserne for matrix B
->ik
angiver indekserne for outputmatrix C
Operationen summerer over indekset j
Den samme kode i Tensorflow ville se ud
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)
Flere eksempler
Indre produkt af vektorer
Det indre produkt (punktprodukt) af to vektorer a og b er defineret som
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.einsum('i,i->', a, b)
print(c) # Output: 32
Ydre produkt af vektorer
Det ydre produkt af to vektorer a og b er givet ved:
C = np.einsum('i,j->ij', a, b)
print(C)
# Output
# [[4 5 6]
# [8 10 12]
# [12 15 18]]
Transponering af en matrix
Transponeringen af en matrix A kan opnås ved at bytte dens indekser
A_transpose = np.einsum('ij->ji', A)
print(A_transpose)
# Output
# [[1. 3.]
# [2. 4.]]
Spor af en matrix
Sporet af en matrix A er summen af dens diagonale elementer:
trace = np.einsum('ii->', A)
print(trace)
# Output: 5.0
Batch Matrix Multiplikation
Einsum er især nyttig til batch-operationer. Antag, at vi har en batch af matricer A og B, og vi vil gange de tilsvarende matricer i batchen:
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)
Her repræsenterer 'b' batchdimensionen.
Fordele ved Einsum-notationen
1. Kortfattethed: Einsum-notationen er kompakt og kan repræsentere komplekse operationer kortfattet
2. Fleksibilitet: Den kan håndtere en bred vifte af tensoroperationer uden eksplicit at omforme eller transponere arrays
3. Effektivitet: Mange biblioteker optimerer einsum-operationerne internt, hvilket potentielt kan føre til bedre ydeevne.