Я бы посоветовал вам не использовать optimize=True
флаг, потому что он неэффективен по какой-то странной причине.Кроме того, я бы порекомендовал вам явно перевести 2D-массив в 3D, выполнить пакетное матричное умножение и затем сжать одноэлементное измерение результирующего массива, если вам в конце понадобится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'
PS Узнайте больше о Понимание NumPy einsum ()