简体   繁体   English

Python中多元正态分布的整合

[英]Integration of Multivariate Normal Distribution in Python

I am trying to integrate over a multivariate distribution in python.我正在尝试在 python 中集成多元分布。 To test it, I built this toy example with a bivariate normal distribution.为了测试它,我用二元正态分布构建了这个玩具示例。 I use nquad() in order to extend it to more than two variables later on.我使用nquad()以便稍后将其扩展到两个以上的变量。 Here is the code:这是代码:

import numpy as np
from scipy import integrate
from scipy.stats import multivariate_normal


def integrand(x0, x1, mean, cov):
    return multivariate_normal.pdf([x0, x1], mean=mean, cov=cov)

mean = np.array([100, 100])
cov = np.array([[20, 0], [0, 20]])

res, err = integrate.nquad(integrand,
                           [[-np.inf, np.inf], [-np.inf, np.inf]],
                           args=(mean, cov))

print(res)

The result I get is 9.559199162933625e-10 .我得到的结果是9.559199162933625e-10 Obviously, this is incorrect.显然,这是不正确的。 It should be (close to) 1.它应该是(接近)1。

What is the problem here?这里有什么问题?

scipy's nquad does numerical integration only on bounded rectangular domains. scipy 的 nquad 仅在有界矩形域上进行数值积分。 The fact that your integral converges at all is due to the exp(-r^2) -type weight of the PDF (see here for its explicit form).您的积分完全收敛的事实是由于 PDF 的exp(-r^2)类型权重(有关其显式形式,请参见此处)。 Hence, you need Hermite quadrature in 2D.因此,您需要 2D 中的Hermite 正交 Some articles exist on this topic, and quadpy (a project of mine) implements those. 有一些关于这个主题的文章quadpy (我的一个项目)实现了这些。

You'll first need to bring your integral into a form that contains the exact weight exp(-r**2) where r**2 is x[0]**2 + x[1]**2 .您首先需要将积分转换为包含精确权重exp(-r**2)的形式,其中r**2x[0]**2 + x[1]**2 Then you cut this weight and feed it into quadpy's e2r2 quadrature:然后你减少这个重量并将它输入到 quadpy 的 e2r2 正交中:

import numpy
import quadpy


def integrand(x):
    return 1 / numpy.pi * numpy.ones(x.shape[1:])


val = quadpy.e2r2.integrate(
    integrand,
    quadpy.e2r2.RabinowitzRichter(3)
    )

print(val)
1.0000000000000004

A bit off-topic, but you should use the following routine instead (it is quite fast):有点跑题,但您应该使用以下例程代替(它非常快):

from scipy.stats.mvn import mvnun
import numpy as np

mean = np.array([100, 100])
cov = np.array([[20, 0], [0, 20]])
mvnun(np.array([-np.inf, -np.inf]), np.array([np.inf, np.inf]), mean, cov)

Or use multivariate_normal.cdf and do the substractions.或者使用multivariate_normal.cdf并做减法。

Thanks for your answer. 感谢您的回答。 I am trying to use quadpy as well, but I am getting the following error message : "AttributeError: module 'quadpy.e2r2' has no attribute 'integrate'". 我也尝试使用Quadpy,但是出现以下错误消息:“ AttributeError:模块'quadpy.e2r2'没有属性'integrate'”。 Have I forgot to call another module, or the synthax has changed ? 我是否忘记调用其他模块,或者Synthax已更改? Thank you in advance. 先感谢您。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM