You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SciPy中正确计算指定箱型区域的多元正态分布概率?

问题描述

需要计算二元正态分布的概率:随机变量满足 (1 < z_1 < 2.178) 且 (2.178 < z_2 < \infty)。该分布均值为0,所有方差均为1,协方差为 (1/\sqrt{2})。

已在R中通过以下代码得到正确结果(约0.0082):

library(mnormt)
sadmvn(lower=c(1, 2.178), upper=c(2.178, Inf), mean=0, varcov=matrix(c(1, 1/sqrt(2), 1/sqrt(2), 1),2, 2))

但在SciPy中尝试的代码得到约0.14的错误结果:

from scipy import stats
import numpy as np

cov = np.array([[1, 1 / np.sqrt(2)], [1 / np.sqrt(2), 1]])
d = stats.multivariate_normal(mean=np.array([0, 0]), cov=cov)
d.cdf([2.178, np.inf]) - d.cdf([1, 2.178])

错误原因

原代码对多维累积分布函数(CDF)的逻辑理解有误:stats.multivariate_normal.cdf([x1, x2]) 计算的是联合概率 (P(z_1 \leq x1, z_2 \leq x2)),直接用 d.cdf([2.178, np.inf]) - d.cdf([1, 2.178]) 无法正确表示目标区间的概率——前者等价于 (P(z_1 \leq 2.178)),后者是 (P(z_1 \leq 1, z_2 \leq 2.178)),两者的差并非目标区间的概率。


正确实现方法

方法1:使用scipy.stats.mvn.mvnun(推荐)

该函数专门用于计算多元正态分布在矩形区域内的概率,功能与R的sadmvn完全对应:

import numpy as np
from scipy.stats import mvn

# 定义分布参数
mean = np.array([0, 0])
cov = np.array([[1, 1 / np.sqrt(2)], [1 / np.sqrt(2), 1]])

# 定义区间边界:lower为各维度下限,upper为各维度上限
lower = np.array([1, 2.178])
upper = np.array([2.178, np.inf])

# 计算概率
prob, _ = mvn.mvnun(lower, upper, mean, cov)
print(prob)  # 输出约为0.0082

方法2:通过联合CDF组合计算

利用联合概率的逻辑推导,拆分目标区间的概率:
目标概率 = (P(z_1 \leq 2.178, z_2 > 2.178) - P(z_1 \leq 1, z_2 > 2.178))
其中 (P(z_j > a, z_i \leq b) = P(z_i \leq b) - P(z_i \leq b, z_j \leq a)),代码实现如下:

from scipy import stats
import numpy as np

cov = np.array([[1, 1 / np.sqrt(2)], [1 / np.sqrt(2), 1]])
d = stats.multivariate_normal(mean=np.array([0, 0]), cov=cov)

# 计算P(z1<=2.178, z2>2.178)
p1 = d.cdf([2.178, np.inf]) - d.cdf([2.178, 2.178])
# 计算P(z1<=1, z2>2.178)
p2 = d.cdf([1, np.inf]) - d.cdf([1, 2.178])
# 目标概率
prob = p1 - p2
print(prob)  # 输出约为0.0082

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 01:22:22