Я бы посоветовал вам не использовать флаг optimize=True
, потому что по какой-то странной причине он неэффективен. Кроме того, я бы рекомендовал вам явно преобразовать 2D-массив в 3D, выполнить пакетное умножение матриц, а затем сжать одноэлементное измерение результирующего массива, если вы в end нужен 2D-массив в качестве конечного результата. Пожалуйста, найдите код ниже:
# sample arrays
In [25]: v1 = np.random.random_sample((3000, 3))
In [26]: v2 = np.random.random_sample((3, 2, 3000))
# Divakar's approach
In [27]: %timeit np.einsum('ij,jki->ik',v1,v2, optimize=True)
80.7 µs ± 792 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# needed for future use
In [28]: res_optimized = np.einsum('ij,jki->ik',v1,v2, optimize=True)
# promoting to 3D array and swapping axes
In [29]: v1 = v1[:, np.newaxis, :]
In [30]: v2 = np.moveaxis(v2, 2, 0)
# perform batch matrix multiplication
In [31]: %timeit np.einsum("bij, bjk -> bik", v1, v2)
47.9 µs ± 496 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# for sanity checking
In [32]: res = np.einsum("bij, bjk -> bik", v1, v2)
In [33]: res.shape, res_optimized.shape
Out[33]: ((3000, 1, 2), (3000, 2))
# squeeze the singleton dimension and perform sanity check with Divakar's approach
In [34]: np.allclose(res.squeeze(), res_optimized)
Out[34]: True
Итак, как мы видим из приведенных выше таймингов, мы выигрываем ок. 2-кратное ускорение без использования флага optimize=True
. Кроме того, явное преобразование массивов в 3D дает немного больше понимания того, что происходит, когда мы используем numpy.einsum()
.
Примечание. Тайминги выполнялись с использованием последней версии NumPy '1.16.1'
.
P.S. Узнайте больше о понимании einsum() NumPy.
person
kmario23
schedule
19.02.2019