You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

两种数值积分方法结果差异:Gauss-Hermite是否更可靠?

关于高斯密度与函数乘积积分的数值方法准确性疑问解答

咱们来聊聊你遇到的这个积分计算问题——用rmutil::int2()和Gauss-Hermite求积法计算同一个高斯密度与函数乘积的积分,结果存在差异,想知道是不是GH方法更准确,而int2的数值积分只是近似?

首先得明确:两种方法本质上都是数值近似,但Gauss-Hermite求积法在处理这类与高斯密度相关的积分时,理论上有天生的精度优势,下面具体拆解:

两种方法的核心差异

  • rmutil::int2():这是一个通用的自适应数值积分工具,针对无穷区间的积分,它会先做变量变换把无穷区间转成有限区间,然后通过逐步细化区间、调整采样点来逼近积分值。它的精度严重依赖于你设置的参数(比如epsmaxd),如果参数不够严格,或者被积函数在某些区域(比如高斯分布的尾部)变化特殊,就容易产生较大的近似误差。
  • Gauss-Hermite求积法:这是专门为计算「函数与高斯密度乘积的积分」设计的正交多项式求积方法。对于单变量的$\int_{-\infty}^{\infty} f(x) e{-x2} dx$,它能通过精心选择的节点和权重,对多项式函数的积分做到精确计算;扩展到多元情况时,通过张量积节点和变量变换(就像你代码里做的那样,把多元正态转换成标准正态形式),只要你的被积函数能被多项式很好地近似,用足够多的节点就能得到极高的精度。

针对你的示例分析

你的被积函数正好是gfun(B0,B1)乘以多元正态密度,完全匹配GH方法的适用场景——GH的权重天生就对应了高斯密度的结构,所以计算效率和精度都比通用的int2高很多。而int2作为通用工具,面对这种带高斯尾的积分,需要更严格的参数设置(比如把eps调到1e-8,增大maxd)才能逼近GH的结果,否则很容易因为区间采样不够细致,导致结果偏差。

验证建议

如果想进一步确认,可以试试这两个操作:

  • 调优int2的参数:把eps设得更小(比如1e-8),同时增大maxd的值,看看结果是否更接近GH的输出。如果是的话,说明之前的int2参数设置不够严格,导致了较大的近似误差。
  • 增加GH的节点数:比如把mgauss.hermite()里的n改成15或20,观察result_GH是否稳定。如果结果几乎不变,说明GH已经收敛到了非常准确的积分值。

你的示例代码

1. rmutil::int2() 实现

library(rmutil)
Sig <- matrix (c(0.2^2, 0, 0, 0.8^2), ncol=2)
Mu<- c(2, 0)
to.integrate <- function(B0, B1) {
  first.int= 1/0.8 * (1.2 * exp(B0 + B1 * 0.5))^(-1/0.8) * gamma(1/0.8)
  B=matrix(c(B0, B1), ncol=1)
  multi.norm=1 / (2 * pi * det(Sig)^(1/2)) * exp (- 0.5 * t( B - Mu ) %*% solve(Sig) %*%( B - Mu ) )
  return (first.int %*% multi.norm)
}
result_int2 <- int2(to.integrate, a=c(-Inf, -Inf), b=c(Inf, Inf), eps=1.0e-6, max=16, d=5)

2. 多元高斯求积点实现

library(statmod)
mgauss.hermite <- function(n, mu, sigma) {
  dm <- length(mu)
  gh <- gauss.quad(n, 'hermite')
  gh <- cbind(gh$nodes, gh$weights)
  idx <- as.matrix(expand.grid(rep(list(1:n), dm)))
  pts <- matrix(gh[idx, 1], nrow(idx), dm)
  wts <- apply(matrix(gh[idx, 2], nrow(idx), dm), 1, prod)
  eig <- eigen(sigma)
  rot <- eig$vectors %*% diag(sqrt(eig$values))
  pts <- t(rot %*% t(pts) + mu)
  return(list(points=pts, weights=wts))
}
nod_wei <- mgauss.hermite(10, mu=Mu, sigma=Sig)
gfun <- function(B0, B1) {
  first.int <- 1/0.8 *(1.2 * exp(B0 + B1 * 0.5))^(-1/0.8)* gamma(1/0.8)
  return(first.int)
}
result_GH <- sum(gfun(nod_wei$points[, 1], nod_wei$points[, 2]) * nod_wei$weights)/pi

总结

简单来说,在处理「被积函数与高斯密度乘积」这类积分时,Gauss-Hermite求积法是更针对性的选择,精度和效率都比通用的自适应积分工具(比如int2)更高。只要节点数足够,它的结果会非常可靠;而int2虽然也能计算,但需要更严格的参数设置才能达到类似的精度,否则容易出现明显的近似误差。

内容的提问来源于stack exchange,提问作者Flora Grappelli

火山引擎 最新活动