文章目录

  • 说明
  • 1、什么是重点抽样法
  • 1.1 随机抽样法
  • 1.2 重点抽样法
  • 2、重点抽样法求积分编程(Matlab)


说明

在学习过程中参考了以下文章或书籍:
《统计计算》

1、什么是重点抽样法

要理解重点抽样法得首先了解随机抽样法,因为重点抽样法就是在随机抽样法的基础上优化得到的。

1.1 随机抽样法

随机抽样法也叫蒙特卡罗方法,简单理解就是采用模拟的方法来逼近真实问题的理论答案。对于求积分的问题而言,随机抽样法又可以分为两种类型:

  1. 随机投点法
  2. 平均值法

以下两个例子,分别对应两种随机抽样法:
例子:

  1. 已知一个函数presto 随机抽样_presto 随机抽样,现在对它求积分,可以把它积分的区域框起来,往其中随机打点,最后统计在函数图形下方的点数presto 随机抽样_M4_02与总点数presto 随机抽样_presto 随机抽样_03的比,再根据矩形框的面积presto 随机抽样_M4_04就可以近似求得积分: presto 随机抽样_均匀分布_05
    对于高维的情况则有类似的:presto 随机抽样_presto 随机抽样_06

    2.依旧是投点,并且假设presto 随机抽样_presto 随机抽样_07坐标符合均匀分布,根据期望的概念:presto 随机抽样_均匀分布_08以及大数定律,可以推导得到这样的积分近似计算方法: presto 随机抽样_均匀分布_09
    同样对于高维情况也有类似的:
    presto 随机抽样_均匀分布_10

1.2 重点抽样法

所谓的重点抽样法,拿这个积分的例子来说,从上图可以看出,在0附近,函数值非常接近0,因此在0附近点落在函数以下的概率很小,大部分都落在了函数上面,从积分的公式可以看出presto 随机抽样_M4_11越具体,求得的结果越精确,0附近显然不利于让presto 随机抽样_M4_11更具体,于是可以让随机投点的重点放在4附近,这样结果就会更精确。

基于平均值法,要想达到这种效果,可以构造一个投点的密度函数presto 随机抽样_presto 随机抽样_13,使得在被积分函数在0附近时投点的概率也比较小,这样就做到了有重点的投点模拟的效果,然后构造一个新的函数:presto 随机抽样_均匀分布_14

再利用期望的概念就可以得到:presto 随机抽样_M4_15

这样一来只需要对presto 随机抽样_M4_16求期望,就相当于在求积分了,而在模拟的过程中也有了重点。

2、重点抽样法求积分编程(Matlab)

被积分函数为:presto 随机抽样_均匀分布_17
辅助函数为(重点抽样法中投点的密度函数):presto 随机抽样_均匀分布_18

% 定义被积函数
f =@(x) x.^3;
% 定义辅助函数(重点抽样法中投点的密度函数)
g =@(x) 3.*x.*x./64.*(x>=0&x<=4);
% 按照辅助函数生成随机数
xxx = slicesample(0.5,1000,'pdf',g)';
% 生成图形中方框的坐标
xs = [repelem(0,100)' linspace(0,4,100)' repelem(4,100)' linspace(4,0,100)'];
ys = [linspace(0,64,100)' repelem(64,100)' linspace(64,0,100)' repelem(0,100)'];
% 随机生成横纵坐标
xx = rand(1,1000)*4;
yy = rand(1,1000)*64;
% 求位于曲线下发的点的个数
zz = yy<f(xx);
times = sum(zz);
% 直接积分得到的结果
resFun1 = integral(f,0,4)
% 随机投点法积分结果
s = times/1000*4*64
% 平均值法积分结果
sAve = (4-0)/1000*sum(f(xx))
% 重点抽样法积分结果
sPUD = mean(f(xxx)./g(xxx))
% 接下来是绘图
myFigure = figure(1);
clf(myFigure)
myAxes = axes("Parent",myFigure);
myLine1 = line(myAxes,0:0.01:4,f(0:0.01:4));
myLine1.Color = 'r';
myLine1.LineStyle = '-';
myLine1.LineWidth = 0.5;
myLine2 = line(myAxes,xs,ys, ...
    'color','b','linestyle','-','linewidth',0.5);
myDots = line(myAxes,xx,yy);
myDots.Color = 'k';
myDots.LineStyle = "none";
myDots.Marker = ".";
myAxes.FontName = "宋体";
myAxes.FontSize = 12;
myAxes.XLim =  [-0.2 4.2];
myAxes.YLim =  [0 70];
myAxes.XLabel.String = "x";
myAxes.YLabel.String = "f(x)";
myAxes.Box = "on";
myAxes.LineWidth = 0.5;

% 接下来是计算结果
resFun1 = 64.0000
s = 62.4640
sAve = 63.3940
sPUD = 64.0965

虽然每次计算的结果可能不一样,但是总体来看,采用重点抽样法的结果要更加接近真实积分值。