Python双变量正常CDF,可变上限

时间:2017-01-11 16:40:43

标签: python normal-distribution cdf

我试图找到一种优雅的方法来计算带有python的双变量正常CDF,其中CDF的一个上界是两个变量的函数,其中一个是二变量正常密度(整数变量)的变量。 / p>

示例:

from scipy import integrate
import numpy as np

# First define f(x, y) as the bivariate normal distribution with fixed correlation p
p = 0.4
def f(x, y):
    Q = x**2 + y**2 - 2*p*x*y
    return 1/(2*np.pi*np.sqrt(1-p**2))*np.exp(-1/(2*(1-p**2))*Q)

# Define N2(a, b) as the cumulative bivariate normal distribution f where a is constant 
# and b is a function of two variables
def N2(a, b):
    prob, error = integrate.dblquad(f, np.NINF, a, lambda x: np.NINF, b)
    return prob

# Upper bound function of 2 variables example where x is an integral variable
def upper_bound(x, v):
    return 0.5*v*x

# My approach which doesn't work
# Calculate bivariate normal CDF for different values of v in the upper bound
results = [N2(1, upper_bound(x, v)) for v in np.linspace(0.01, 4, 200)]

关于我如何改变我的方法以便调用upper_bound(x, v)的任何想法  results = [N2(1, upper_bound(x, v)) for v in np.linspace(0.01, 4, 200)]可行吗?解决这个问题的其他方法也很受欢迎。

编辑:这是我想要计算的积分,其中f(x,y)是双变量正态密度函数。请注意,我想要计算的实际上限f(x,v)= 0.5 * v * x更复杂,这只是一个例子,因此我不想象征性地计算它,例如用sympy。此外,我的目标是计算几百个不同的v。

值的积分

积分:enter image description here

1 个答案:

答案 0 :(得分:1)

虽然这种方法很慢但似乎有效。

前几行,直到'这应该产生1',是一个完整性检查。我想验证我的方法是否能正确计算密度下的体积。确实如此。

我使用方差 - 协方差矩阵来获得0.4的期望相关性,并避免编写我自己的pdf。

我在两个地方调整函数,以便函数只有一个参数。这使得可以将内积分计算为 x 的函数。它还可以在 v 参数外面使用'其他计算。

from toolz import curry
from scipy.stats import multivariate_normal
from scipy.integrate import quad
import numpy as np

@curry
def bivariate(x,y):
    return multivariate_normal.pdf([x,y],cov=[[1,.4],[.4,1]])

def out_y(x):
    marginal = bivariate(x)
    return quad(marginal, np.NINF, np.PINF)[0]

# this should produce 1
print (quad(out_y, np.NINF, np.PINF)[0])

# now to what the OP wants

@curry
def inner_integral(v,x):
    marginal = bivariate(x)
    return quad(marginal, np.NINF, 0.5*v*x)[0]

inner_integral_for_one_v = inner_integral(0.8)
print (quad(inner_integral_for_one_v,np.NINF, 1)[0])

要使用此代码,您可以编写相当于:

的内容
for v in range(0,1,0.1):
    inner_integral_for_one_v = inner_integral(v)
    print (quad(inner_integral_for_one_v,np.NINF, 1)[0])