我想知道是否可以使用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]
范围内。近似输出不是一个选项,因为返回的向量后来被赋予评估函数 - 近似可能返回相同的向量以获得相似的输入,因此它不是一个选项。
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)))
答案 0 :(得分:4)
要在没有cython
或jit
的情况下更快地运行代码将会非常困难,一些数学技巧可能会更容易。在我看来,如果我们在正N中为k(g, b) = f1(g, b, n+1, t1, t2)/f1(g, b, n, t1, t2)
定义n
,k
函数的限制应为t1+t2
(还没有可靠的证据) ,只是一种直觉;它可能是E(g)= 0& E(p)= 0的特殊情况。)。对于t1=1
和t2=0.5
,k()
似乎很快就达到了极限,对于N>100
,它几乎是1.5
的常量。
所以我认为数值近似方法应该是最简单的方法。
In [81]:
t2=0.5
data=[f1(g, b, i+2, t1, t2)/f1(g, b, i+1, t1, t2) for i 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])
答案 1 :(得分:4)
我毫不犹豫地将此作为答案,因为我认为它可能是您提供给我们的输入数据的工件。不过请注意tanh(x) ~ 1
为x>>1
。您输入的数据在我运行时始终为x = np.dot(p,b) >> 1
,因此我们可以将f1
替换为f2
。
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
def f2(g, b, dt, t1, t2):
p = np.copy(g)
for i in range(dt):
p += t1 + t2*p
return p
print np.allclose(f1(g,b,dt,t1,t2), f2(g,b,dt,t1,t2))
这确实表明这两个函数在数值上是等价的。请注意,f2是non-homogeneous linear recurrence relation,如果您选择这样做,可以一步完成。