所以我一直试图适应指数修正的高斯函数(如果感兴趣,https://en.wikipedia.org/wiki/Exponentially_modified_Gaussian_distribution)
import numpy as np
import scipy.optimize as sio
import scipy.special as sps
def exp_gaussian(x, h, u, c, t):
z = 1.0/sqrt(2.0) * (c/t - (x-u)/c) #not important
k1 = k2 = h * c / t * sqrt(pi / 2) #not important
n1 = 1/2 * (c / t)**2 - (x-u)/t #not important
n2 = -1 / 2 * ((x - u) / c)**2 #not important
y = np.zeros(len(x))
y += (k1 * np.exp(n1) * sps.erfc(z)) * (z < 0)
y += (k2 * np.exp(n2) * sps.erfcx(z)) * (z >= 0)
return y
为了防止溢出问题,必须使用两个等效函数中的一个,具体取决于z是正还是负(参见上一维基百科页面的替代计算表格)。
我遇到的问题是:当z为正时,行y += (k2 * np.exp(n2) * sps.erfcx(z)) * (z >= 0)
仅应添加到y。但是,如果z是,例如-30,sps.erfcx(-30)
是inf
,则inf * False是NaN。因此,不是使y保持不变,而是将所得的y与NaN聚集在一起。例如:
x = np.linspace(400, 1000, 1001)
y = exp_gaussian(x, 100, 400, 10, 5)
y
array([ 84.27384586, 86.04516723, 87.57518493, ..., nan,
nan, nan])
我尝试用以下内容替换相关行:
y += numpy.nan_to_num((k2 * np.exp(n2) * sps.erfcx(z)) * (z >= 0))
但这样做会遇到严重的运行时问题。有没有办法只在(k2 * np.exp(n2) * sps.erfcx(z))
条件下评估(z >= 0)
?是否有其他方法可以在不牺牲运行时的情况下解决这个问题?
谢谢!
编辑:在Rishi的建议之后,以下代码似乎工作得更好:
def exp_gaussian(x, h, u, c, t):
z = 1.0/sqrt(2.0) * (c/t - (x-u)/c)
k1 = k2 = h * c / t * sqrt(pi / 2)
n1 = 1/2 * (c / t)**2 - (x-u)/t
n2 = -1 / 2 * ((x - u) / c)**2
return = np.where(z >= 0, k2 * np.exp(n2) * sps.erfcx(z), k1 * np.exp(n1) * sps.erfc(z))
答案 0 :(得分:3)
如何使用np.where(z >= 0, sps.erfcx(z), sps.erfc(z))
来Rect
。我不是一个笨拙的专家,所以不知道它是否有效。至少看起来很优雅!
答案 1 :(得分:0)
您可以做的一件事是创建一个遮罩并重复使用它,因此不需要对其进行两次评估。另一个想法是在结尾只使用一次nan_to_num
mask = (z<0)
y += (k1 * np.exp(n1) * sps.erfc(z)) * (mask)
y += (k2 * np.exp(n2) * sps.erfcx(z)) * (~mask)
y = numpy.nan_yo_num(y)
试试看这是否有帮助...