使用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?
答案 0 :(得分:4)
虽然我并不完全熟悉QUADPACK,但自适应集成通常可以通过提高分辨率来实现,直到答案不再提高为止。在大多数间隔期间(F(10)==9.356e-116
),你的函数非常接近0,对于四边形选择的初始网格点,改进可以忽略不计,并且它决定积分必须接近于0.基本上,如果你的数据隐藏在整合范围的一个非常狭窄的子区间内,quad
最终无法找到它。
对于从0
到inf
的集成,间隔显然不能细分为有限数量的间隔,因此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)
并仔细分析详细输出来调试它。如果答案不满意,很抱歉。