跳转至

1D 蒙特卡洛积分解释

来源: Monte Carlo Integration Explanation in 1D - The blog at the bottom of the sea


1. 引言

我们考虑一个简单的问题:想知道函数

\[ y = \sin^2(x) \]

在区间 \(x \in [0,\pi]\) 下,曲线下面积是多少。

用传统的微积分可以精确解出为

\[ \int_0^{\pi} \sin^2(x)\,dx = \frac{\pi}{2} \]

2. 示例问题

我们希望计算:

\[ I = \int_{0}^{\pi} \sin^2(x)\,dx \]

解析答案为:

\[ I = \frac{\pi}{2} \approx 1.5708 \]

3. 基本蒙特 卡罗积分方法

方法思路如下:

  1. 在区间 [0, π] 内均匀随机抽取 \(x_i\)
  2. 对每个样本计算 \(y_i = f(x_i) = \sin^2(x_i)\)
  3. 计算平均值:
\[ \bar{y} = \frac{1}{N}\sum_{i=1}^{N} y_i \]
  1. 将平均值乘以区间宽度得到积分估计:
\[ I \approx (b-a)\cdot\bar{y} = (\pi - 0)\cdot \bar{y} \]

完整表达式为

\[ \int_{a}^{b} f(x)\,dx \approx (b-a)\cdot \frac{1}{N}\sum_{i=1}^{N} f(x_i) \]

4. 示例代码(C++)

double SimpleMonteCarlo()
{
    double rangeMin = 0;
    double rangeMax = 3.14159265359;  // π
    size_t numSamples = 10000;

    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(rangeMin, rangeMax);

    double ySum = 0.0;
    for (size_t i = 0; i < numSamples; ++i)
    {
        double x = dist(mt);
        double y = sin(x) * sin(x);
        ySum += y;
    }

    double yAverage = ySum / double(numSamples);
    double width = rangeMax - rangeMin;
    return width * yAverage;
}

5. 样本数与误差关系

误差大约随下式衰减:

\[ \text{误差} \propto \frac{1}{\sqrt{N}} \]

要让误差减半,需要 4 倍样本数。
虽然收敛慢,但它的优点是收敛速率与维度无关

6. 抽样策略优化

为减少方差,可采用以下抽样优化方法:

  • 蓝噪声 (Blue Noise):避免样本聚集。
  • 低差异序列 (Low Discrepancy Sequences):如 Sobol、Halton 序列。
  • 分层抽样 (Stratified Sampling)
\[ I \approx (b-a)\cdot\frac{1}{M}\sum_{k=1}^{M} f(x_k) \]

保证每个子区间都有样本。

7. 任意分布抽样(PDF 抽样)

如果从任意分布 \(p(x)\) 抽样:

\[ \int_a^b f(x)\,dx = \int_a^b \frac{f(x)}{p(x)}\,p(x)\,dx \approx \frac{1}{N}\sum_{i=1}^N \frac{f(x_i)}{p(x_i)}, \quad x_i \sim p(x) \]

\(p(x)\)\(f(x)\) 形状接近时,可显著降低方差。
这就是重要抽样 (Importance Sampling)

8. 总结

核心思想:

\[ \int f(x)\,dx \approx \text{期望}[f(x)] \]
优点 缺点
实现简单、通用、高维有效 收敛慢、噪声大