Как я могу наиболее эффективно вычислить точечные произведения 2 ND внешних произведений из 1D массивов?
"i, j, k, l-> ij, kl->" было бы хорошей альтернативой einsum, ноэто терпит неудачу.
invalid subscript ',' in einstein sum subscripts string, subscripts must be letters
Ниже приведены наивные реализации, которые я пытаюсь ускорить (A и B будут другими вещами).Идеальным вариантом будет быстрая версия со следующим API, которая будет иметь тот же результат, что и следующие примеры: nd_outer_from1D (2, A, B), nd_outer_from1D (3, A, B).Как вы увидите, по мере того, как | A |, | B | и N увеличиваются, сохраняя результат и снова вставляя его в einsum, поскольку аргументы быстро становятся невозможными.
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); sum(sum(np.outer(A,A) * np.outer(B,B)))'
10000 loops, best of 3: 72.1 usec per loop
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); sum(sum(np.einsum("i,j->ij",A,A) * np.einsum("i,j->ij",B,B) ))'
10000 loops, best of 3: 61.4 usec per loop
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); sum(sum(sum(np.einsum("i,j,k->ijk",A,A,A) * np.einsum("i,j,k->ijk",B,B,B) )))'
1000 loops, best of 3: 1.78 msec per loop
Правка (пример):
>>> A
array([0, 1, 2, 3])
>>> B
array([0.58394169, 0.22495002, 0.08322459, 0.05406281])
>>> sum(sum(np.einsum('i,j->ij',A,A) * np.einsum('i,j->ij', B, B)))
0.3064592592321492
Видимо сумма (сумма (и начальная эйнсум не сработала, как я ожидал).
Кусок торта для гуру ниже, сравнивая времена:
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); np.einsum("i,i->",A,B)**3'
100000 loops, best of 3: 6.77 usec per loop
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); np.einsum("i,i->",A,B)**2'
100000 loops, best of 3: 6.63 usec per loop
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); A.dot(B)**3'
100000 loops, best of 3: 3.75 usec per loop
$ python -m timeit 'import numpy as np; A=np.arange(50); B=np.arange(50); A.dot(B)**2'
100000 loops, best of 3: 3.68 usec per loop
Ого, этобыстрее, чем я ожидал:
$ python -m timeit 'import numpy as np; A=np.arange(5000); B=np.arange(5000); A.dot(B)**10'
100000 loops, best of 3: 12.1 usec per loop