使用scipy.integrate.quad时结果不连续

时间:2014-06-02 21:36:57

标签: python matlab numpy fortran numerical-methods

使用scipy.integrate.quad时,我发现了一种奇怪的行为。这种行为也出现在Octave的quad函数中,这让我相信它可能与QUADPACK本身有关。有趣的是,使用完全相同的Octave代码,这种行为出现在MATLAB中。

关于这个问题。我在数字上整合了各种边界的对数正态分布。因为F是对数正态的cdf,a是下界,b是上界,我发现在某些条件下,

当p是“非常大的数字”时,

积分(F,a,b)= 0,而

积分(F,a,b)=当b为np.inf时的正确极限。 (或者只是Infave for Octave。)

这是一些示例代码,用于显示它的实际效果:

from __future__ import division
import numpy as np
import scipy.stats as stats
from scipy.integrate import quad

# Set up the probability space:
sigma = 0.1
mu = -0.5*(sigma**2)  # To get E[X] = 1
N = 7
z = stats.lognormal(sigma, 0, np.exp(mu))


# Set up F for integration:
F = lambda x: x*z.pdf(x)

# An example that appears to work correctly:
a, b = 1.0, 10
quad(F, a, b)
# (0.5199388..., 5.0097567e-11)

# But if we push it higher, we get a value which drops to 0:
quad(F, 1.0, 1000)
# (1.54400e-11, 3.0699e-11)

# HOWEVER, if we shove np.inf in there, we get correct answer again: 
quad(F, 1.0, np.inf)
# (0.5199388..., 3.00668e-09)


# If we play around we can see where it "breaks:"
quad(F, 1.0, 500)   # Ok
quad(F, 1.0, 831)   # Ok
quad(F, 1.0, 832)   # Here we suddenly hit close to zero. 
quad(F, 1.0, np.inf)   # Ok again 

这里发生了什么?为什么quad(F,1.0,500)估计大致正确的东西,但对于所有值832< = b< 4,quad(F,1.0,b)变为零。 np.inf?

2 个答案:

答案 0 :(得分:4)

虽然我并不完全熟悉QUADPACK,但自适应集成通常可以通过提高分辨率来实现,直到答案不再提高为止。在大多数间隔期间(F(10)==9.356e-116),你的函数非常接近0,对于四边形选择的初始网格点,改进可以忽略不计,并且它决定积分必须接近于0.基本上,如果你的数据隐藏在整合范围的一个非常狭窄的子区间内,quad最终无法找到它。

对于从0inf的集成,间隔显然不能细分为有限数量的间隔,因此quad在计算积分之前需要进行一些预处理。例如,更改y=1/(1+x)等变量会将时间间隔0..inf映射到0..1。细分该间隔将从原始函数中抽取接近于零的更多点,从而使quad能够找到您的数据。

答案 1 :(得分:2)

尝试降低容错率

>>> quad(F, a, 1000, epsabs=1.49e-11)
(0.5199388058383727, 2.6133800952484582e-11)

我猜数值积分只对某些配置敏感。您可以尝试通过调用quad(..., full_output=1)并仔细分析详细输出来调试它。如果答案不满意,很抱歉。