Scipy - 仅在函数输入值改变时执行函数的一部分

时间:2011-12-08 04:54:29

标签: python numpy scipy

我一直在尝试优化此代码:

def spectra(mE, a):
    pdf = lambda E: np.exp(-(a+1)*E/mE)*(((a+1)*E/mE)**(a+1))/(scipy.special.gamma(a+1)*E)
    u=[]
    n=np.random.uniform()
    E=np.arange(0.01,150, 0.1)
    for i in E: 
        u.append(scipy.integrate.quad(pdf,0,i)[0])

    f=interp1d(u, E)
    return f(n)

我试图用f创建一个查找表,但似乎每次调用该函数时它都会重新进行集成。有没有办法放入类似if语句的东西,这样我就可以为fmE的值创建a一次,之后再调用它?

感谢您的帮助。

干杯。

2 个答案:

答案 0 :(得分:2)

如果使用相同的(mE, a)值重新调用函数,那么您想要做的就是返回一个已知值,如果输入是新的,则执行计算。

这称为 memoization 。请参阅示例What is memoization and how can I use it in Python?。请注意,在现代版本的Python中,您可以创建一个装饰器来应用函数的memoization,这样可以让您更加整洁。

答案 1 :(得分:0)

很可能你不能存储 spectrum(x,y)的值,并通过精确浮点 x的值合理地检索它们 y 。在现实生活中,您很少遇到完全相同的浮点值。

请注意,我认为您不能直接缓存f,这取决于很长的浮动列表。可能的输入空间太大,以至于发现一个接近的匹配对我来说似乎是不太可能的。

如果缓存spectra()的值,则可以合理的概率检索足够接近的参数对的值。

问题在于寻找如此紧密的配对。哈希表无法工作(我们需要不精确的匹配),有序列表和二进制搜索也无法工作(我们有2个维度)。我会使用quad tree或其他形式的spatial index。您可以动态有效地构建它,搜索您给定点附近的最近已知点。

如果您发现缓存的点非常接近您需要的点,您只需返回缓存的值即可。如果没有足够接近的点,则将其添加到索引中,希望将来可以重用它。如果您的点位于两个已知点之间,也许您甚至可以进行插值。

先决条件当然是缓存中有足够数量的点可以重用。要估计这一点,运行您的一些计算并在某处(例如在文件中)存储(mE, a)对,然后绘制它们。你会立即看到你是否有一组彼此接近的点。当然,你也可以在没有绘图的情况下寻找紧密的集群。如果您有足够紧密的群集(您可以将一个点的值重用于另一个点),您的缓存将起作用。如果没有,请不要打扰它。