Каковы значения подписок, передаваемых numpy.einsum ()? - PullRequest
2 голосов
/ 17 мая 2019

Я пытаюсь понять код Python, который использует numpy.einsum() для преобразования 4-мерного массива numpy A в 2- или 3-мерные массивы. Подписи, переданные на numpy.einsum(), следующие:

Mat1 = np.einsum('aabb->ab', A) 

Mat2 = np.einsum('abab->ab', A)

Mat3 = np.einsum('abba->ab', A) 

T1 = np.einsum('abcb->abc' A)

T2 = np.einsum('abbc->abc', A)

и т.д.. Следуя ответам ( Понимание einsum NumPy ) и ( Python - Sum 4D Array ), я попытался использовать numpy.sum(), чтобы понять значения приведенных выше индексов, например, Mat1 = np.sum(A, axis=(0,3)) но я не смог воспроизвести результаты, которые я получаю с numpy.einsum(). Может кто-нибудь объяснить, как эти подписки интерпретируются в numpy.einsum()?

1 Ответ

2 голосов
/ 18 мая 2019

Советую прочитать нотация Эйнштейна в Википедии .

Вот краткий ответ на ваш вопрос:

np.einsum('aabb->ab', A)

означает:

res = np.empty((max_a, max_b), dtype=A.dtype)
for a in range(max_a):
  for b in range(max_b):
    res[a, b] = A[a, a, b, b]
return res

Краткое объяснение:
aabb означает индексы и их равенство (см. A[a, a, b, b]);
->ab означает, что форма (max_a, max_b), и вам не нужно, чтобы два имели сумму по этим двум индексам. (если бы они были c также, то вы должны суммировать все по c, поскольку оно не представлено после ->)


Другие ваши примеры:

np.einsum('abab->ab', A)

# Same as (by logic, not by actual code)

res = np.empty((max_a, max_b), dtype=A.dtype)
for a in range(max_a):
  for b in range(max_b):
    res[a, b] = A[a, b, a, b]
return res
np.einsum('abba->ab', A) 

# Same as (by logic, not by actual code)

res = np.empty((max_a, max_b), dtype=A.dtype)
for a in range(max_a):
  for b in range(max_b):
    res[a, b] = A[a, b, b, a]
return res
np.einsum('abcb->abc', A)

# Same as (by logic, not by actual code)

res = np.empty((max_a, max_b, max_c), dtype=A.dtype)
for a in range(max_a):
  for b in range(max_b):
    for c in range(max_c):
      res[a, b, c] = A[a, b, c, b]
return res
np.einsum('abbc->abc', A)

# Same as (by logic, not by actual code)

res = np.empty((max_a, max_b, max_c), dtype=A.dtype)
for a in range(max_a):
  for b in range(max_b):
    for c in range(max_c):
      res[a, b, c] = A[a, b, b, c]
return res

Некоторый код, чтобы проверить, что это действительно так:

import numpy as np


max_a = 2
max_b = 3
max_c = 5

shape_1 = (max_a, max_b, max_c, max_b)
A = np.arange(1, np.prod(shape_1) + 1).reshape(shape_1)

print(A)
print()
print(np.einsum('abcb->abc', A))
print()

res = np.empty((max_a, max_b, max_c), dtype=A.dtype)
for a in range(max_a):
  for b in range(max_b):
    for c in range(max_c):
      res[a, b, c] = A[a, b, c, b]

print(res)
print()

...