我试图用scipy计算一个明确的双积分。被积函数有点复杂,因为它包含一些概率分布来衡量x和y的每个值的可能性(如混合模型)。以下代码计算为负数,但应由[0,1]绑定。此外,计算需要大约半个小时。
我有两个问题。
1)有没有更好的方法来计算这个积分?
2)这个负值来自哪里?对我来说最大的问题是如何加快计算速度,因为我可以在我的代码中找到导致我自己的负面影响的错误。
from scipy import stats
from scipy.integrate import dblquad
import itertools
p= [list whose entries are each different stats.beta(a,b) distributions]
def integrand(x,y):
delta=x-y
marg=0
for distA,distB in itertools.permutations(p,2):
first=distA.pdf(x)
second=distB.pdf(y)
weight1=0
weight2=0
for distC in p:
if distC == distA:
continue
w1=distC.cdf(x)-distC.cdf(y)
if weight1 == 0:
weight1=w1
else:
weight1=weight1*w1
marg+=(first*weight1*second)
I=delta*marg
return I
expect=dblquad(integrand,0,1,lambda x: 0, lambda x: x)
这基本上要求两个点之间的最大距离的期望值在分布向量中是什么。积分的极限是yε[0,x]和xε[0,1]。这给了我大约-.49,估计误差为10e-10,所以它不应该归因于积分方法。
我一直在与此作斗争并感谢任何帮助。感谢。
编辑:纠正错误
答案 0 :(得分:1)
有几种方法可以提高计算速度。
您可以使用epsabs
和epsrel
参数dblquad
来增加整合的效果。当然,你的结果会不太准确,但是对于调试来说这很好。
您可以通过重新排序代码(警告,未经测试的代码)来大幅减少integrand
中的功能评估数量
def integrand(x, y):
marg = 0.0
cdf = dict((id(distC), distC.cdf(x) - distC.cdf(y)) for distC in p)
for distA in p:
weight = numpy.prod(cdf[id(distC)]
for distC in p if distC is not distA)
marg += weight * distA.pdf(x) * sum(
distB.pdf(y) for distB in p if distB is not distA)
return (x-y) * marg
但请注意,Python对函数调用有相当大的开销,因此在纯Python中编写它不会让你太过分(对Cython这样的问题可能会有所帮助)。
我不知道为什么积分变为负数。也许我可以告诉你,如果你想给p
做一个例子 - 这将使我们能够真正尝试你的代码。
答案 1 :(得分:0)
积分方法给出的误差只是一个数字,告诉你收敛行为有多好。您是否尝试计算被积函数的显式值?
顺便问一下:你在整合pdf吗?如果是:您确定您的集成限制吗?