在很长的时间间隔内积分高斯

时间:2019-05-13 10:42:53

标签: python scipy integral

我想在一个很大的时间间隔内集成一个高斯函数。我选择了辣.integrate.quad函数进行集成。仅当我选择足够小的间隔时,该功能才起作用。当我使用以下代码时,

from scipy.integrate import quad
from math import pi, exp, sqrt

def func(x, mean, sigma):
    return 1/(sqrt(2*pi)*sigma) * exp(-1/2*((x-mean)/sigma)**2) 

print(quad(func, 0, 1e+31, args=(1e+29, 1e+28))[0]) # case 1
print(quad(func, 0, 1e+32, args=(1e+29, 1e+28))[0]) # case 2
print(quad(func, 0, 1e+33, args=(1e+29, 1e+28))[0]) # case 3
print(quad(func, 1e+25, 1e+33, args=(1e+29, 1e+28))[0]) # case 4

然后打印以下内容。

1.0
1.0000000000000004
0.0
0.0

为了获得合理的结果,我不得不尝试几次更改积分的上下限,并凭经验将其确定为[0,1e + 32]。这对我来说是冒险的,因为当高斯函数的均值和西格玛改变时,我总是必须尝试不同的界限。

有没有一种清晰的方法可以将函数从0集成到1e + 50,而不会打扰到边界?如果不是,您如何从一开始就期望哪个边界将给出非零值?

2 个答案:

答案 0 :(得分:1)

简而言之,你不能。

在这个较长的时间间隔内,高斯不为零的区域很小,并且在integrate.quad框架下工作的自适应过程看不到它。除非偶然,否则几乎任何自适应例程都将如此。

答案 1 :(得分:0)

通知

enter image description here

,并且正常随机变量的CDF被称为ϕ(x),因为它不能由elementary function表示。因此,以ϕ((b-m)/s) - ϕ((a-m)/s)为例。另请注意,ϕ(x) = 1/2(1 + erf(x/sqrt(2)))不需要调用.quad来实际执行集成,并且可能会更好地与scipy中的erf一起使用。

from scipy.special import erf

def prob(mu, sigma, a, b):
    phi = lambda x: 1/2*(1 + erf((x - mu)/(sigma*np.sqrt(2))))
    return phi(b) - phi(a)

这可能会给出更准确的结果(比上面的结果更准确)

>>> print(prob(0, 1e+31, 0, 1e+50))
0.5
>>> print(prob(0, 1e+32, 1e+28, 1e+29))
0.000359047985937333
>>> print(prob(0, 1e+33, 1e+28, 1e+29))
3.5904805169684195e-05
>>> print(prob(1e+25, 1e+33, 1e+28, 1e+29))
3.590480516979522e-05

,并避免您遇到严重的floating point错误。但是,您集成的区域面积很小,您可能仍会看到0