Acordo e einsum de Einstein

Surpreendentemente, no segmento de língua russa da Internet, quase não há material que explique o acordo de soma de Einstein em uma linguagem compreensível . Não é menos surpreendente que haja ainda menos materiais para entender como a função einsum funciona na Internet de língua russa. Em inglês, há uma resposta bastante detalhada sobre o trabalho de einsum no estouro da pilha, e em russo existem apenas alguns sites que fornecem uma tradução em curva dessa mesma resposta. Quero resolver este problema de falta de materiais e convido todos os interessados ​​a lerem!






Discutindo o Acordo Einstein

Em primeiro lugar, gostaria de observar que a concordância de Einstein é mais frequentemente usada na análise de tensores e suas aplicações, portanto, mais adiante no artigo haverá várias referências a tensores.

Quando você apenas começa a trabalhar com tensores, pode ficar confuso que, além dos subscritos usuais, sobrescritos também são usados, o que a princípio geralmente pode ser tomado como exponenciação. Exemplo:

"a com i sobrescrito" será escrito como a ^ ie "a em um quadrado com i sobrescrito" (a ^ i) ^ 2. Pode ser confuso e desconfortável no início, mas você pode se acostumar com o tempo.





Acordo: mais adiante no artigo, objetos do tipo a_ix_iou a_ix ^ ivou chamá-los de termos .





Sobre o que é o acordo de Einstein?

O acordo de Einstein visa reduzir o número de sinais de soma em uma expressão. Existem três regras simples que determinam o quão correta uma expressão é escrita na notação de Einstein.





Regra # 1: A soma é realizada em todos os índices que se repetem duas vezes em um termo.



Exemplo: considere uma expressão como esta:





\ sum_ {i = 1} ^ 3 a_ix_i = a_1x_1 + a_2x_2 + a_3x_3

Usando a convenção de Einstein, esta expressão pode ser reescrita assim:





a_ix_i \ text {ou} a_ix ^ i

Assim, eliminamos o sinal de soma e apenas escrevemos um único termo. Note que neste termo o índice i se repete duas vezes, o que significa que, de acordo com a primeira regra, entendemos que o somatório é feito sobre o índice i, ou seja, sobre todos os valores possíveis que este índice assume.







: A \ in \ mathbb {R} ^ {m \ vezes n} v \ in \ mathbb {R} ^ {n}. b \ in \ mathbb {R} ^ {m}. :





b_i = \ sum \ limits_ {j = 1} ^ n A_ {ij} v_j, ~ i = 1, \ ldots, m

:





b_i = A_ {ij} v_ {j} = A_ {ij} v ^ {j}

, i , j , , j.





1. , , .





2. , .





, , ,





  1. .





  2. , .





, Python:





for i in range(M):
    for j in range(N):
        b[i] += A[i, j] * v[j]
      
      



, , . j , i – . . j .





№ 2. .





, a_ {ij} b_ {ij}, a_ {ii} b_ {ij} a_ {ij} b_ {jj}, , .

:





a_i ^ i– i , .. ;





a_i ^ {jj}– i , j – ;





a_ {ii} ^ {jj}– i, j ;





a_ {ij} ^ {ij}– i, j ;





a_ {ii} ^ {ij}– ( i );





, , , . :





a_ {ij} b_ {i} + a_ {ji} b_ {j}

, , . , , , i 3 , j, , , ( ), , .





№ 3. , .





:





b_i = A_ {ij} v_ {j}– , i , ;





a_i = A_ {ki} B_ {kj} x_ {j} + C_ {ik} u_ {k}– . : k j , , , i , , . k , i – , , k – , i – . i , , . : i , , 3 .





, :





x_i = A_ {ij}– i , i j;





x_j = A_ {ik} u_k– j, i. ;





x_i = A_ {ik} u_k + c_j– i, i, j;





:

UMA – . , :





A_ {i_1i_2i_3i_4i_5} = \ sum_ {j_4 = 1} ^ {R_4} \ sum_ {j_3 = 1} ^ {R_3} \ sum_ {j_2 = 1} ^ {R_2} \ sum_ {j_1 = 1} ^ {R_1} G ^ {(1)} _ {i_1j_1} G ^ {(2)} _ {j_1i_2j_2} G ^ {(3)} _ {j_2i_3j_3} G ^ {(4)} _ {j_3i_4j_4} G ^ {(5)} _ {j_4i_5}

, G ^ {(k)}, R_i. – . , .

, i_1, i_2, i_3, i_4, i_5, , j_1, j_2, j_3, j_4. , , , , . , G ^ {(k)}, (k). , , . :





A_ {i_1i_2i_3i_4i_5} = \ left (G ^ {(1)} \ right) _ {i_1j_1} \ left (G ^ {(2)} \ right) _ {i_2j_2} ^ {j_1} \ left (G ^ {( 3)} \ right) _ {i_3j_3} ^ {j_2} \ left (G ^ {(4)} \ right) _ {i_4j_4} ^ {j_3} \ left (G ^ {(5)} \ right) _ { i_5} ^ {j_4}

, !





einsum

einsum , Python (NumPy, TensorFlow, PyTorch). , , ( , ), , einsum . NumPy. einsum . , , , , .





: A \ in \ mathbb {R} ^ {3 \ times5}, B \ in \ mathbb {R} ^ {5 \ times2} – , . M \ in \ mathbb {R} ^ {3 \ times2}, , :





M_ {ij} = \ sum_ {k = 1} ^ {5} A_ {ik} B_ {kj} = A_ {ik} B_ {kj}

. , :





M = np.zeros((3, 2))
for i in range(3):
    for j in range(2):
        for k in range(5):
            M[i, j] += A[i, k] * B[k, j]
      
      



, einsum :





M = np.einsum("ik,kj->ij", A, B)
      
      



, . einsum : , . :





"{, },{, }->{, }"





einsum :





  • ( ), ;





  • , ;





  • 3 ;





, einsum , , , . , , , , einsum . , einsum.





, einsum:





einsum,

1. :





vector = np.array([1, 2, 3, 4, 5])
result = np.einsum("i->", vector)
print(result)
      
      



Output

15





2. :





matrix = np.array([[1, 2], [3, 4], [5, 6]])
result = np.einsum("ij->", matrix)
print(result)
      
      



Output

21





3. :





matrix = np.array([[1, 2], [3, 4], [5, 6]])
result = np.einsum("ij->j", matrix)
print(result)
      
      



Output

[9, 12]





4. :





matrix = np.array([[1, 2], [3, 4], [5, 6]])
result = np.einsum("ij->i", matrix)
print(result)
      
      



Output

[3, 7, 11]





5. ( , , , ):





matrix = np.array([[1, 2], [3, 4], [5, 6]])
result = np.einsum("ij->ji", matrix)
print(result)
      
      



Output

[[1, 3, 5], [2, 4, 6]]





6. :





matrix = np.array([[1, 2], [3, 4], [5, 6]])
vector = np.array([[1, 2]])
result = np.einsum("ij,kj->ik", matrix, vector)
print(result)
      
      



, 1 \ vezes 2, , . einsum , , , .





Output

[[5], [11], [17]]





7. :





matrix1 = np.array([[1, 2], [3, 4], [5, 6]])
matrix2 = np.array([[1, 0], [0, 1]])
result = np.einsum("ik,kj->ij", matrix1, matrix2)
print(result)
      
      



Output

[[1, 2], [3, 4], [5, 6]]





8. :





vector1 = np.array([[1, 2, 3]])
vector2 = np.array([[1, 1, 1]])
result = np.einsum("ik,jk->", vector1, vector2)
print(result)
      
      



Output

6





9. :





matrix1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
result = np.einsum("ii->", matrix1)
print(result)
      
      



Output

15





10. () :





matrix1 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
matrix2 = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
result = np.einsum("ij,ij->ij", matrix1, matrix2)
print(result)
      
      



, , : , einsum – :





result = np.zeros(matrix1.shape, dtype="int32")
for i in range(result.shape[0]):
    for j in range(result.shape[1]):
        result[i, j] += matrix1[i, j] * matrix2[i, j]
print(result)
      
      



Output

[[1, 0, 0], [0, 5, 0], [0, 0, 9]]





11. () :





vector1 = np.array([1, 2, 3])
vector2 = np.array([1, 0, 0])
result = np.einsum("i,j->ij", vector1, vector2)
print(result)
      
      



Output

[[1, 0, 0], [2, 0, 0], [3, 0, 0]]





12. :





A = np.array([[[0, 1], [1, 2], [2, 3]], [[1, 2], [2, 3], [3, 4]], [[2, 3], [3, 4], [4, 5]]])
result = np.einsum("ijk->jki", A)
print(result)
      
      



Output

[[[0, 1, 2], [1, 2, 3]], [[1, 2, 3], [2, 3, 4]], [[2, 3, 4], [3, 4, 5]]]





13. :





A = np.array([[[0, 1], [1, 2], [2, 3]], [[1, 2], [2, 3], [3, 4]], [[2, 3], [3, 4], [4, 5]]])
U = np.array([[1, 2], [2, 3]])
result = np.einsum("ijk,nk->ijn", A, U)
print(result)
      
      



Output

[[[2, 3], [5, 8], [8, 13]], [[5, 8], [8, 13], [11. 18]], [[8, 13], [11, 18], [14, 23]]]





, einsum . , (np.dot, np.outer, np.tensordot, np.transpose, np.cumsum ..), einsum. , , , , , .





einsum ( ).





Acordo de Einstein (base)





Acordo de Einstein (parte avançada)








All Articles