4. 蒙特卡洛模拟实战

蒙特卡洛模拟的核心思想可以用一句话概括:把不确定的输入看成随机变量,按各自的分布反复抽样,把每一组样本代入工程模型算出一个输出,最后用大量输出的统计特征来近似真实的不确定性传播结果。本节围绕一个具体的工程模型,把随机数生成、样本量选择、收敛性判断、置信区间估计和Python实现串成一条可执行的链路。

一、选定一个可手算校核的工程模型

考虑一根承受轴向拉力的圆截面钢杆,其承载力模型为:

R = fy * A = fy * (π * d² / 4)
S = F
安全裕度 g = R - S

其中屈服强度 fy、直径 d、荷载 F 均视为随机变量。假设(示例假设,非实测数据):fy 服从正态分布 N(235, 15²) MPa;d 服从正态分布 N(20, 0.5²) mm;F 服从正态分布 N(60000, 6000²) N。由于 d 以平方形式进入模型,输出 R 的分布会明显偏离正态,这正是蒙特卡洛相对一阶二阶矩法(FOSM)的优势所在——它不需要线性化近似。

二、随机数生成:从均匀数到目标分布

计算机只能产生伪随机均匀数 U(0,1),其他分布都要通过变换得到。工程上最常用的是逆变换法:若 U~Uniform(0,1),则 X = F⁻¹(U) 服从累积分布函数为 F 的分布。对正态分布,等价于 X = μ + σ·Φ⁻¹(U),Python 中由 norm.ppf 或直接 norm.rvs 完成。实际实现时有三个要点必须注意:

  • 固定随机种子:用 np.random.default_rng(2024) 创建生成器,保证结果可复现,便于他人校核与排障。
  • 使用新式 Generator 接口:避免旧的 np.random.seed 全局状态,多变量抽样时用同一个 rng 对象依次调用,保证样本之间相互独立。
  • 检查分布参数:正态分布允许负值,若物理量不可能为负(如直径),应改用对数正态或截断正态,否则会引入不合理的样本。

三、样本量选择与收敛性判断

样本量 N 决定了统计量的抽样误差。若关注输出均值,其标准误约为 σg/√N,因此要把均值误差减半,样本量需增至 4 倍。若关注失效概率 Pf,则相对误差大致与 1/√(N·Pf) 成正比:当 Pf≈10⁻³ 时,取 N=10⁵ 才约有 10% 的相对误差,这也是小失效概率问题需要方差缩减技术(重要抽样等)的原因。

收敛性不能只看一个总数,而应观察统计量随 N 的稳定过程。实用做法是:把 N 个样本按累积顺序计算运行均值与运行标准差,绘制收敛曲线;同时把总样本分成若干批(如 20 批),计算批均值的标准差,若批均值波动已小于目标精度,可认为收敛。另一个有效手段是重复独立模拟若干次(不同种子),比较各次得到的均值与失效概率,若离散程度满足要求即可停止加样。

蒙特卡洛不确定性传播:从输入分布到输出统计 输入随机变量 fy ~ N(235, 15²) MPa d ~ N(20, 0.5²) mm F ~ N(60000, 6000²) N rng = default_rng(2024) 逆变换法 / norm.rvs 独立抽样 N 组 样本矩阵 N×3 工程模型 R = fy·π·d²/4 S = F g = R − S 向量化计算 输出样本 g₁…g_N 输出统计与判读 均值 μ_g ≈ 13800 N,标准差 σ_g 失效概率 P_f = P(g<0) ≈ 1.2% 95% 置信区间:μ_g ± 1.96·σ_g/√N P_f 区间:Wilson 或 Bootstrap 收敛判据:批均值波动 < 目标精度 (数值为示例假设结果) 收敛性判断:运行均值随样本量 N 的变化 N(对数刻度) μ_g 目标精度带 ±ε 初期波动大 进入稳定区,可停止加样 收敛点

四、置信区间估计

得到输出样本后,均值 μg 的 95% 置信区间为 x̄ ± 1.96·s/√N,其中 s 为样本标准差。当 N 较大时该区间近似可靠;N 较小时应改用 t 分布分位数。对于失效概率 Pf,直接用 p̂ ± 1.96·√(p̂(1−p̂)/N) 在 p̂ 接近 0 或 1 时会失效,推荐使用 Wilson 区间,或对样本做 Bootstrap 重抽样(如 2000 次)得到经验分位数区间。工程报告中应同时给出点估计与区间,否则读者无法判断结果的可信程度。

五、Python 实现

import numpy as np
from scipy.stats import norm

rng = np.random.default_rng(2024)
N = 100_000

fy = rng.normal(235, 15, N)      # MPa
d  = rng.normal(20, 0.5, N)      # mm
F  = rng.normal(60000, 6000, N)  # N

R = fy * np.pi * d**2 / 4
g = R - F

mu, sd = g.mean(), g.std(ddof=1)
ci = (mu - 1.96*sd/np.sqrt(N), mu + 1.96*sd/np.sqrt(N))
pf = np.mean(g < 0)

# Wilson 区间
z = 1.96
den = 1 + z**2/N
center = (pf + z**2/(2*N)) / den
half = z*np.sqrt(pf*(1-pf)/N + z**2/(4*N**2)) / den
print(f"μ_g={mu:.1f} N, 95%CI=({ci[0]:.1f},{ci[1]:.1f})")
print(f"P_f={pf:.4%}, Wilson=({center-half:.4%},{center+half:.4%})")

运行后(示例假设结果)可得到 μg 约 1.38×10⁴ N,Pf 约 1.2%,与图中示意一致。注意 g < 0 的写法在 HTML 中需转义,实际脚本中直接写 g < 0 即可。

六、结果判读与常见陷阱

判读时先看收敛曲线是否进入目标带,再看置信区间宽度是否满足工程精度要求,最后检查失效概率区间是否跨越决策阈值。常见陷阱包括:用同一随机数流重复抽样导致样本相关;忽略单位换算(MPa 与 mm² 相乘得 N,需与荷载单位一致);对偏态输出直接套用正态区间;以及只报告单次模拟结果而不做重复验证。把种子、样本量、分布参数和区间方法一并记录,模拟结果才具备可追溯性。