Допустим, у вас есть 2 относительно больших массива a
и b
.Вы можете использовать широковещание для создания dot
продукта:
a = np.random.normal(size=(1000, 300))
b = a*2
ref = a.dot(b.T)
res = (a[:,None,:]*b[None,:,:]).sum(2)
np.allclose(ref, res)
# True
timeit -n 1 -r 5 a.dot(b.T)
# 17.6 ms
timeit -n 1 -r 5 (a[:,None,:]*b[None,:,:]).sum(2)
# 1.83 s
Разница в производительности составляет примерно 2 порядка, даже больше для больших массивов.np.dot
намного быстрее, потому что он использует специализированные библиотеки, а также потому, что он не хранит в памяти полный временной массив a[:,None,:]*b[None,:,:]
np.dot
всегда умножает, а затем уменьшает сумму.Интересно, можно ли заменить операцию умножения на любую другую поэлементную операцию (например, np.maximum
, ==
, np.power
...) и уменьшение суммы на другую операцию сокращения, такую как np.max
.Я знаю, что у этого были бы нишевые приложения реального мира, но я думаю, что это могло бы быть полезно в некоторых случаях.
Я пытался использовать numexpr
, но у него ограниченная поддержка funcs и dtypes.
Я также пытался создать массив с dype=object
, с пользовательскими методами умножения и суммирования, но тогда вы больше не имеете дело со смежными кусками памяти.
Есть ли эффективный способ сделать это в numpy?
В идеале некоторая функция с синтаксом: np.custom_dot(a,b, elementwise_func=my_func, redux_func=my_other_func)