python - Can I speed up this basic linear algebra code? -
i wondering whether possible optimise following using numpy
or mathematical trickery.
def f1(g, b, dt, t1, t2): p = np.copy(g) in range(dt): p += t1*np.tanh(np.dot(p, b)) + t2*p return p
where g
vector of length n
, b
n
xn
matrix, dt
number of iterations, , t1
, t2
are scalars.
i have ran out of ideas on how optimise further, because p
used within loop, in 3 terms of equation: when added itself; in dot product; , in scalar multiplication.
but maybe there different way represent function or there other tricks improve efficiency. if possible, prefer not use cython
etc., i'd willing use if speed improvements significant. in advance, , apologies if question out of scope somehow.
update:
the answers provided far more focused on values of input/output avoid unnecessary operations. have updated mwe proper initialisation values variables (i didn't expect optimisation ideas come side -- apologies). g
in range [-1, 1]
, b
in range [-infinity, infinity]
. approximating output not option because returned vectors later given evaluation function -- approximation may return same vector similar input, not option.
mwe:
import numpy np import timeit iterations = 10000 setup = """ import numpy 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) 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__': function in functions: print(function) print('time = {}'.format(timeit.timeit(function, setup=setup, number=iterations)))
to code running faster without cython
or jit
hard, mathematical trickery may more easier approach. appears me if define k(g, b) = f1(g, b, n+1, t1, t2)/f1(g, b, n, t1, t2)
n
in positive n, k
function should have limit of t1+t2
(don't have solid proof yet, gut feeling; may special case e(g)=0 & e(p)=0 also.). t1=1
, t2=0.5
, k()
appears approach limit quickly, n>100
, constant of 1.5
.
so think numerical approximation approach should easiest one.
in [81]: t2=0.5 data=[f1(g, b, i+2, t1, t2)/f1(g, b, i+1, t1, t2) in range(1000)] in [82]: plt.figure(figsize=(10,5)) plt.plot(data[0], '.-', label='1') plt.plot(data[4], '.-', label='5') plt.plot(data[9], '.-', label='10') plt.plot(data[49], '.-', label='50') plt.plot(data[99], '.-', label='100') plt.plot(data[999], '.-', label='1000') plt.xlim(xmax=120) plt.legend() plt.savefig('limit.png') in [83]: data[999] out[83]: array([ 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5])
Comments
Post a Comment