Zapis Einsteinovega seštevka je jedrnat in zmogljiv način za predstavitev tenzorskih operacij, ki se pogosto uporablja v fiziki in strojnem učenju. Omogoča nam pisanje kompleksnih izračunov na tenzorjih v kompaktni obliki. Obravnavali bomo osnove Einsteinovega seštevanja, kako ga uporabljati v Pythonu z Numpy in Tensorflow ter podali primere za ponazoritev njegove uporabe.
Osnove Einsteinovega seštevanja
Einsteinov zapis seštevanja (Einsum) temelji na ideji seštevanja ponavljajočih se indeksov v tenzorskih izrazih. Temelji na naslednjih dveh pravilih:
1. Seštevanje ponavljajočih se indeksov: Če se indeks pojavi dvakrat v izrazu, se sešteje
2. Prosti indeksi: Indeksi, ki se pojavijo samo enkrat, so prosti indeksi in predstavljajo osi izhodnega tenzorja
Ponazorimo to s primerom množenja dveh matrik A in B: nastala matrika C je definirana kot
V Pythonu tako knjižnici Numpy kot Tensorflow zagotavljata funkcijo 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]]
V zgornjem primeru je ij,jk->ik
niz einsum:
ij
predstavlja indekse matrike A
jk
predstavlja indekse matrike B
->ik
podaja indekse izhodne matrike C
Operacija sešteje nad indeksom j
Ista koda v Tensorflow bi izgledala takole
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)
Več primerov
Notranji produkt vektorjev
Notranji produkt (pikasti produkt) dveh vektorjev a in b je definiran kot
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
c = np.einsum('i,i->', a, b)
print(c) # Output: 32
Zunanji produkt vektorjev
Zunanji produkt dveh vektorjev a in b je podan z:
C = np.einsum('i,j->ij', a, b)
print(C)
# Output
# [[4 5 6]
# [8 10 12]
# [12 15 18]]
Transponiranje matrike
Transpozicijo matrike A lahko dobimo z zamenjavo njenih indeksov
A_transpose = np.einsum('ij->ji', A)
print(A_transpose)
# Output
# [[1. 3.]
# [2. 4.]]
Sled matrice
Sled matrike A je vsota njenih diagonalnih elementov:
trace = np.einsum('ii->', A)
print(trace)
# Output: 5.0
Paketno množenje matrik
Einsum je še posebej uporaben za paketne operacije. Recimo, da imamo paket matrik A in B in želimo pomnožiti ustrezne matrike v paketu:
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)
Tu b
predstavlja dimenzijo serije.
Prednosti zapisa Einsum
1. Jedrnatost: Zapis Einsum je kompakten in lahko jedrnato predstavlja kompleksne operacije
2. Fleksibilnost: Obvladuje najrazličnejše tenzorske operacije brez eksplicitnega preoblikovanja ali prenosa nizov
3. Učinkovitost: Številne knjižnice interno optimizirajo operacije einsum, kar lahko vodi do boljše učinkovitosti.