蒙特卡洛模拟计算Y的期望与方差:结果异常排查请求
首先咱们先明确问题背景:
已知混合分布X满足:P(X=0)=7/8,P(XExp(1/60))=1/8;年度故障次数NPois(2),年度总维修成本Y是N次维修的成本之和。理论上E[Y]=15,Var(Y)=1800,但你的代码算出的期望正确,方差却不符合理论值。
接下来拆解代码里的两个核心错误:
1. 混合分布X的模拟逻辑错误
你的代码里用expon_dis[l] * (1/8)来表示单次维修成本X,这完全搞错了X的混合分布定义。X的正确逻辑是:7/8的概率取0,1/8的概率直接取Exp(1/60)的样本,而不是把Exp(1/60)的结果缩放1/8。
为什么期望刚好对?这是个巧合:Exp(1/60)的期望是60,乘以1/8后是7.5,和真实的E[X]=(7/8)*0 + (1/8)*60=7.5刚好相等。但方差就完全错了:真实的Var(X)=E[X²]-(E[X])²,其中Exp(λ)的二阶矩是2/λ²,所以E[X²]=(1/8)2(60)²=900,Var(X)=900-7.5²=843.75;而你模拟的错误X的方差是Var(Exp(1/60)/8)=3600/64=56.25,差了15倍。
2. 总维修成本Y的计算逻辑错误
Y是N次独立维修的成本之和,也就是当N=n时,Y=X₁+X₂+…+Xₙ(每个Xᵢ都是独立的混合分布)。但你的代码里用(expon_dis[l] * (1/8)) * (N[l]),这相当于把单次错误X的结果乘以N,而不是n个独立X的和。
这两者的方差天差地别:
- 正确的方差:Var(X₁+…+Xₙ)=n*Var(X)(独立同分布)
- 错误的方差:Var(nX)=n²Var(X)
加上之前X的模拟错误,最终方差结果自然和理论值1800相差甚远。
修正后的代码
下面是修复后的蒙特卡洛模拟代码,同时计算期望和方差:
# 补充定义模拟次数(原代码未定义,这里设为1000次) runs <- 1000 set.seed(123) # 设置随机种子,保证结果可复现 # 存储每次模拟的均值和方差 sim_means <- numeric(runs) sim_vars <- numeric(runs) for (u in 1:runs) { n_samples <- 200 # 模拟200个样本的故障次数N N <- rpois(n_samples, 2) # 初始化总维修成本Y的向量 Y <- numeric(n_samples) for (l in 1:n_samples) { n_faults <- N[l] if (n_faults == 0) { Y[l] <- 0 } else { # 生成n_faults个独立的混合分布X样本 # 每个X有7/8概率为0,1/8概率服从Exp(1/60) X_samples <- ifelse(runif(n_faults) < 1/8, rexp(n_faults, 1/60), 0) # 总维修成本是n_faults次维修的成本之和 Y[l] <- sum(X_samples) } } # 记录本次模拟的Y的均值和方差 sim_means[u] <- mean(Y) sim_vars[u] <- var(Y) } # 输出模拟结果的平均值 cat("模拟期望的平均值:", round(mean(sim_means), 2), "\n") cat("模拟方差的平均值:", round(mean(sim_vars), 2), "\n")
运行这段代码后,你会发现模拟的方差均值会接近理论值1800,期望也稳定在15左右。
总结
你的代码之所以期望正确是巧合(缩放后的X期望刚好等于真实X的期望),但两个核心逻辑错误导致方差完全偏离:
- 错误地用缩放指数分布的方式模拟混合分布X
- 错误地用单次X乘N代替N个独立X的求和来计算总维修成本Y
修正这两点后,模拟结果就会和理论值一致啦。
内容的提问来源于stack exchange,提问作者FlubberBeer

