Мне было интересно, можно ли оптимизировать следующее с помощью Numpy или математического обмана.
def f1(g, b, dt, t1, t2):
p = np.copy(g)
for i in range(dt):
p += t1*np.tanh(np.dot(p, b)) + t2*p
return p
где g - вектор длины n, b - это матрица n x n, dt - число итераций, а t1 и t2 - скаляры.
Я быстро исчерпал идеи о том, как оптимизировать это дальше, потому что p используется в цикле во всех трех терминах уравнения: при добавлении к себе; в точечном продукте; и в скалярном умножении.
Но, возможно, есть другой способ представить эту функцию или есть другие трюки, чтобы повысить ее эффективность. Если возможно, я бы предпочел не использовать Cython и т.д., Но я был бы готов использовать его, если бы улучшения скорости были значительными. Заранее спасибо, и извиняюсь, если вопрос вне сферы видимости.
Обновление:
Представленные ответы до сих пор более сфокусированы на том, какие значения ввода/вывода могут быть во избежание ненужных операций. Теперь я обновил MWE с правильными значениями инициализации для переменных (я не ожидал, что идеи оптимизации придут с этой стороны - извинения). g будет находиться в диапазоне [-1, 1], а b будет находиться в диапазоне [-infinity, infinity]. Аппроксимация вывода не является опцией, потому что возвращенные векторы позже передаются функции оценки - аппроксимация может возвращать один и тот же вектор для довольно аналогичного ввода, поэтому это не вариант.
MWE:
import numpy as np
import timeit
iterations = 10000
setup = """
import numpy as np
n = 100
g = np.random.uniform(-1, 1, (n,)) # Updated.
b = np.random.uniform(-1, 1, (n,n)) # Updated.
dt = 10
t1 = 1
t2 = 1/2
def f1(g, b, dt, t1, t2):
p = np.copy(g)
for i in range(dt):
p += t1*np.tanh(np.dot(p, b)) + t2*p
return p
"""
functions = [
"""
p = f1(g, b, dt, t1, t2)
"""
]
if __name__ == '__main__':
for function in functions:
print(function)
print('Time = {}'.format(timeit.timeit(function, setup=setup,
number=iterations)))
