4、随机变量抽样:逆变换法、接受-拒绝法、Box-Muller变换、常用分布抽样实现

蒙特卡洛模拟的核心在于用随机数驱动模型演化,而随机数的质量与抽样效率直接决定模拟结果的精度与计算成本。在工程实践中,我们通常先获得均匀分布 U(0,1) 的随机数(由线性同余发生器或梅森旋转算法产生),再通过特定变换将其映射为目标分布。本章围绕四种经典抽样方法展开:逆变换法(Inverse Transform)、接受-拒绝法(Acceptance-Rejection)、Box-Muller 变换以及常用分布的直接抽样实现。理解这些方法的适用边界与数值稳定性,是构建高效蒙特卡洛引擎的基础能力。

随机变量抽样方法总览 均匀随机数 U(0,1) 逆变换法 F⁻¹(U) 解析或数值求逆 接受-拒绝法 包络函数 c·g(x) 采样 Box-Muller 变换 极坐标 → 标准正态 常用分布直接抽样 泊松/二项/指数等 适用:CDF 可解析求逆 适用:PDF 有界、包络易采样 适用:正态分布生成 适用:特定分布专用算法 目标分布随机样本 X ~ F(x) 关键考量 数值稳定性 | 计算效率 | 尾部分布精度 | 高维扩展性 | 随机数质量

4.1 逆变换法:从 CDF 反函数出发

核心原理

逆变换法基于概率积分变换定理:若随机变量 X 的累积分布函数为 F(x),则 Y = F(X) 服从 U(0,1) 均匀分布。反之,若 U ~ U(0,1),则 X = F⁻¹(U) 服从分布 F。该方法要求 F(x) 严格单调且可解析求逆,或至少能通过数值方法高效求解。

操作流程

  1. 推导 CDF:明确目标分布的累积分布函数 F(x) 及其定义域。
  2. 求逆函数:解析求解 x = F⁻¹(u),若无法解析则准备数值求根方案(如二分法、牛顿法)。
  3. 生成均匀随机数:调用随机数发生器产生 u ~ U(0,1)。
  4. 映射:计算 x = F⁻¹(u),即为目标分布的一个样本。

案例拆解:指数分布抽样

指数分布的概率密度函数为 f(x) = λe^(-λx),x ≥ 0,其 CDF 为 F(x) = 1 - e^(-λx)。令 u = 1 - e^(-λx),解得 x = -ln(1-u)/λ。由于 1-u 与 u 同分布,可简化为 x = -ln(u)/λ。这一简洁形式使指数分布成为逆变换法最经典的教科书案例。

工程要点:当 λ 很大时(如 λ = 1000),x 的取值集中在 0 附近,此时浮点数精度可能影响 -ln(u) 的计算。建议使用双精度并避免 u 恰好等于 0(部分 RNG 可能产生 0 值)。

常见误区

  • 忽略定义域:逆变换法要求 F 在定义域上严格单调,对于分段函数需逐段处理。
  • 数值求逆的精度:当 F 接近 0 或 1 时,数值求逆的相对误差可能放大,导致尾部样本失真。
  • 误用离散分布:离散分布的 CDF 是阶梯函数,逆变换需通过查找表实现,而非简单解析求逆。

4.2 接受-拒绝法:用包络分布逼近目标

核心原理

当目标分布 f(x) 的 CDF 难以求逆时,接受-拒绝法提供了一种通用替代方案。其思想是:选择一个容易抽样的建议分布 g(x),并找到常数 c ≥ 1 使得 c·g(x) ≥ f(x) 对所有 x 成立。然后从 g(x) 中抽取候选样本 Y,再从 U(0,1) 中抽取 u,若 u ≤ f(Y)/(c·g(Y)) 则接受 Y,否则拒绝并重试。

判断方法与效率分析

关键指标 公式/含义 工程建议
接受概率 P(accept) = 1/c c 越接近 1,效率越高;c 过大则大量样本被浪费
包络条件 c·g(x) ≥ f(x), ∀x 需在目标分布支撑集上逐点验证
建议分布选择 g(x) 应形状接近 f(x) 常用均匀分布、正态分布或 t 分布作为包络
尾部行为 c·g(x) 与 f(x) 的尾部比值 尾部若包络不足,会产生系统性偏差

案例拆解:从半正态分布抽样

假设目标分布为截断正态分布 f(x) ∝ exp(-x²/2),x ∈ [0, 3]。选择建议分布 g(x) = U(0,3) 的均匀分布,则需找到 c 使得 c/3 ≥ f(x) 在 [0,3] 上成立。f(x) 在 x=0 处取最大值 1/√(2π) ≈ 0.399,因此 c = 3 × 0.399 ≈ 1.197。接受概率约为 1/c ≈ 0.835,效率尚可。若将区间扩展到 [0, 10],则 c 需增大至 3.99,接受概率降至 0.25,此时应改用指数分布作为建议分布以提升效率。

风险提示:接受-拒绝法的最大隐患是包络条件在数值上被违反。当目标分布具有重尾或高尖峰时,建议分布的选择需格外谨慎。建议在实现后通过直方图对比或 KS 检验验证样本质量。

常见误区

  • c 值选取过小:若 c·g(x) 在某些区域小于 f(x),则会产生偏差样本,且该偏差难以通过增大样本量消除。
  • 忽略建议分布的支撑集:g(x) 的支撑集必须完全覆盖 f(x) 的支撑集,否则目标分布尾部将无法被采样。
  • 效率评估缺失:未计算接受概率就投入大规模模拟,可能导致计算资源浪费。

4.3 Box-Muller 变换:高效生成正态分布

核心原理

Box-Muller 变换利用二维均匀分布到二维正态分布的映射关系。设 U₁, U₂ 为两个独立的 U(0,1) 随机数,则:

Z₁ = √(-2·ln U₁) · cos(2π·U₂)
Z₂ = √(-2·ln U₁) · sin(2π·U₂)

得到的 Z₁, Z₂ 为两个独立的标准正态分布 N(0,1) 样本。该方法的数学基础是极坐标变换:将均匀分布的点映射到高斯分布的径向与角度分量。

操作流程与数值稳定性

  1. 生成两个独立均匀随机数 u₁, u₂。
  2. 计算 r = √(-2·ln u₁),θ = 2π·u₂。
  3. 输出 z₁ = r·cos θ,z₂ = r·sin θ。

实际工程中,更推荐使用极坐标形式的改进版(Marsaglia polar method),它避免了三角函数调用,计算速度更快且数值更稳定:

do {
  x = 2·u₁ - 1;  y = 2·u₂ - 1;
  s = x² + y²;
} while (s ≥ 1 || s == 0);
z₁ = x · √(-2·ln s / s);
z₂ = y · √(-2·ln s / s);
经验分享:Box-Muller 变换一次生成两个正态样本,在需要大量正态随机数的场景(如金融蒙特卡洛中的几何布朗运动模拟)中,可显著减少 RNG 调用次数。但需注意,若 RNG 质量不佳(如周期过短),两个样本之间的相关性可能被引入。

案例拆解:金融资产价格路径模拟

在期权定价中,几何布朗运动模型 dS = μS dt + σS dW 的离散化需要生成标准正态随机数。假设模拟 10,000 条路径、每条路径 252 个时间步,共需 2,520,000 个正态样本。使用 Box-Muller 变换,每次调用生成 2 个样本,仅需 1,260,000 次 RNG 调用。若使用逆变换法(正态 CDF 无解析逆),需调用数值求逆函数,单次耗时约为 Box-Muller 的 3-5 倍。实测中,Box-Muller 配合 Marsaglia 极坐标法可将路径模拟总耗时降低约 40%。

常见误区

  • u₁ = 0 导致无穷大:部分 RNG 可能产生 0 值,需做保护处理(如取 max(u₁, 1e-12))。
  • 忽略相关性检验:若 RNG 的周期不够长,Box-Muller 生成的两个样本可能呈现微弱负相关,影响模拟精度。
  • 误用单精度:在计算 √(-2·ln u₁) 时,单精度浮点数在 u₁ 接近 1 时精度不足,建议使用 double。

4.4 常用分布的直接抽样实现

核心原理与实现策略

除上述通用方法外,许多常用分布拥有专用抽样算法,这些算法在效率、数值稳定性和实现复杂度之间取得了平衡。下表总结了典型分布的推荐抽样方法:

分布 推荐方法 关键公式/步骤 注意事项
指数分布 Exp(λ) 逆变换法 x = -ln(u)/λ λ 较大时注意浮点精度
正态分布 N(μ, σ²) Box-Muller / Marsaglia z = √(-2·ln u₁)·cos(2πu₂) 避免 u₁=0;建议使用极坐标法
泊松分布 Pois(λ) Knuth 算法(λ 较小) 累乘均匀数直到乘积 < e^(-λ) λ 较大时改用正态近似或 PTRD 算法
二项分布 Bin(n, p) BTPE 算法 基于接受-拒绝的专用算法 n 很大时可用正态近似
Gamma 分布 Marsaglia-Tsang 方法 基于接受-拒绝的改进 形状参数 k 较小时需特殊处理
贝塔分布 Beta(α, β) Johnk 方法 / 比值法 利用 Gamma 样本比值 α, β 均小于 1 时需谨慎

案例拆解:泊松分布抽样的工程实现

在排队论模拟中,顾客到达过程通常建模为泊松过程。假设平均到达率 λ = 5 人/分钟,需要生成 10,000 分钟的到达人数。Knuth 算法实现如下:

function poissonSample(lambda) {
  double L = Math.exp(-lambda);
  double p = 1.0;
  int k = 0;
  do {
    k++;
    p *= Math.random();
  } while (p > L);
  return k - 1;
}

当 λ = 5 时,平均每次调用需生成约 6 个均匀随机数,效率尚可。但当 λ = 1000 时,Knuth 算法平均需生成 1001 个随机数,效率急剧下降。此时应改用 PTRD(Poisson-Triangle-Review-Draw)算法或正态近似(λ > 1000 时近似精度已足够)。

实战建议:在工程代码中,建议将分布抽样封装为独立模块,并针对不同参数范围自动选择算法。例如,泊松分布 λ < 30 用 Knuth,λ ≥ 30 用 PTRD 或正态近似。这种自适应策略可兼顾精度与效率。

常见误区与总结复盘

  • 一刀切使用逆变换法:正态分布、Gamma 分布等 CDF 无解析逆,强行数值求逆会损失效率。
  • 忽略参数边界:如泊松分布 λ 极大时,Knuth 算法退化;Beta 分布参数小于 1 时,Johnk 方法可能失效。
  • 未验证样本质量:任何抽样算法实现后,都应进行分布拟合检验(如 KS 检验、卡方检验)和相关性检验。
  • 随机数质量被忽视:底层 RNG 的周期、均匀性和独立性直接影响所有抽样方法的效果。建议使用梅森旋转(MT19937)或 PCG 等高质量 RNG。
最终提醒:蒙特卡洛模拟的精度不仅取决于抽样方法,还取决于样本量、方差缩减技术和模型假设。抽样方法的选择应在精度、速度和实现复杂度之间取得平衡。对于生产级应用,建议对抽样模块进行单元测试,使用已知分布的统计量(均值、方差、偏度)进行验证。