其他分享
首页 > 其他分享> > 蒙特卡洛积分——非均匀采样

蒙特卡洛积分——非均匀采样

作者:互联网

  为什么需要蒙特卡洛法积分呢?数学上,积分的解析解,往往需要求出被积分函数的原函数,这对于计算机是相当困难的,因此有了求积分的数值方法。

均匀采样

  假设我们现在要求\(x^2\)在\([0,2]\)上的积分

效果图

  如何计算这块面积呢,不妨将其看成“矩形”进行计算,矩形的宽为2,高为\(x^2\)在\([0,2]\)上的均值。

\[S=2*average(x^{2}) \]

  我们取越多的点来估算均值,获得的结果也越精确。

  如何严格证明我们估算正确性呢?

  下面是我们要估算的真实值,即\(x^2\)在\([0,2]\)上的积分

效果图

  蒙特卡洛积分表述为以下形式:

效果图

  则有:

效果图

  由于估计量的数学期望等于被估计参数的真实值,所以我们的估计是无偏的。

非均匀采样

  如果不按均匀采样,而是按\(p(x)\)的概率密度进行采样,同样也可以达到效果。

  只是此时,f(x)还需要除以p(x),相当于出现概率更大的点,计算时赋予的权重就低一点

  蒙特卡洛的积分形式为:

效果图

  下面我们来证明其正确性

效果图

  因此非均匀采样的估计也是无偏的。

蒙特卡洛积分

  下面是一个蒙特卡洛积分的简单示例

#include <iostream>
using namespace std;

//被积函数
double test_func(float x){
	return x * x;
}
inline double random() {
	return rand() / (RAND_MAX + 1.0);
}

inline double pdf(double x){
	return 3 * x*x / 8;
}

int main()
{
	int N = 10000;
	double sum = 0;
	for (int i = 0; i < N; i++){
		float x = pow(8 * random(), 1.0 / 3.0); //这里取CDF的反函数,详见上一篇文章
		sum += test_func(x) / pdf(x); // 本篇所述,1/pdf(x)的权重
	}
	cout << "I =" << sum / N << endl;
	return 0;
}

//输出:I =2.66667

标签:采样,return,积分,double,均匀,蒙特卡洛
来源: https://www.cnblogs.com/mingyangovo/p/14672027.html