Einstein Summation-notasjonen er en kortfattet og kraftig måte å representere tensoroperasjoner på, ofte brukt i fysikk og maskinlæring. Det lar oss skrive komplekse beregninger på tensorer i en kompakt form. Vi vil dekke det grunnleggende om Einstein-summering, hvordan du bruker det i Python med Numpy og Tensorflow, og gir eksempler for å illustrere bruken.
Grunnleggende om Einstein-oppsummering
Einstein Summation-notasjonen (Einsum) er basert på ideen om å summere over gjentatte indekser i tensoruttrykk. Den er basert på følgende to regler:
1. Summering over gjentatte indekser: Hvis en indeks vises to ganger i en term, summeres den over
2. Frie indekser: Indekser som vises bare én gang er frie indekser og representerer aksene til utgangstensoren
La oss illustrere dette med eksemplet med å multiplisere to matriser A og B: den resulterende matrisen C er definert som
I Python gir både Numpy- og Tensorflow-bibliotekene en einsum-funksjon.
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
representerer indeksene til matrise A
"jk" representerer indeksene til matrise B
->ik
spesifiserer indeksene til utmatrisen C
Operasjonen summerer over indeksen j
Den samme koden i Tensorflow ville se ut
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 av vektorer
Det indre produktet (punktproduktet) av to vektorer a og b er definert som
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.einsum('i,i->', a, b)
print(c) # Output: 32
Ytre produkt av vektorer
Det ytre produktet av to vektorer a og b er gitt av:
C = np.einsum('i,j->ij', a, b)
print(C)
# Output
# [[4 5 6]
# [8 10 12]
# [12 15 18]]
Transponer en matrise
Transponeringen av en matrise A kan oppnås ved å bytte dens indekser
A_transpose = np.einsum('ij->ji', A)
print(A_transpose)
# Output
# [[1. 3.]
# [2. 4.]]
Spor av en matrise
Sporet til en matrise A er summen av dens diagonale elementer:
trace = np.einsum('ii->', A)
print(trace)
# Output: 5.0
Batch Matrix Multiplikasjon
Einsum er spesielt nyttig for batchoperasjoner. Anta at vi har en gruppe med matriser A og B, og vi ønsker å multiplisere de tilsvarende matrisene i gruppen:
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 representerer 'b' batchdimensjonen.
Fordeler med Einsum-notasjonen
1. Kortfattethet: Einsum-notasjonen er kompakt og kan representere komplekse operasjoner kortfattet
2. Fleksibilitet: Den kan håndtere en lang rekke tensoroperasjoner uten eksplisitt å omforme eller transponere arrays
3. Effektivitet: Mange biblioteker optimaliserer einsum-operasjonene internt, noe som kan føre til bedre ytelse.