Monte Carlo

随机数生成

线性同余法

若要生成 $[0,1]$上的随机数,可通过如下递推式生成伪随机数:

$$ r_{i+1}= (ar_i+c)\mathrm{mod}M $$

所得${r_i/ M}$即想要的随机数。

a=5;c=1;r1=3;m=2^8
N=1000;%随机数个数
r=zeros(1,N);
for i=1:N
    r(i)=mod(a*r1+c,m);
    r1=r(i);
end
figure; plot(1:N,r/m,'-*')

MC 积分

直接抽样:考虑 $x_i \sim \mathrm{rand}(0,1)$服从随机分布,积分等价于求 $f(x_i)$的期望 $$ I= \int_{0}^1f(x)\mathrm{d}x =\lim_{N \to \infty} \frac{1}{N} \sum_{i=1}^{N}f(x_i) $$

缺点:往往需要较大的样本量才能达到较小的误差。

重要抽样

考虑变量 $x_i\sim w(x)$,其中: $$ \int_{0}^1w(x)\mathrm{d}x=1 $$

利用 :

$$ y(x)=\int_{0}^{x}w(x’)\mathrm{d} x’ $$

则原积分可以表示为:

$$ I= \int_{0}^1 \frac{f(x(y))}{w(x(y))}\mathrm{d}y =\lim_{N \to \infty} \frac{1}{N} \sum_{i=1}^{N}\frac{f(x(y_i))}{w(x(y_i))} $$

其中$y_i \sim \mathrm{rand}(0,1)$,如果 $\frac{f}{w}\sim \mathrm{const}$则抽样良好。

难点:构造合适的分布 $w(x)$与求反函数 $x(y)$。

特定随机分布数构造

Gauss 分布

$$ w(x)=\frac{1}{\sqrt{2\pi}}e^{\frac{1}{2}x^2} $$

由概率论:

$$ \frac{1}{12}\overline{\mathrm{rand}(0,1)}-6\sim N(0,1) $$

%Gauss分布的随机数;

N=100000;
Gauss=zeros(1,N);
for i=1:12
    Gauss=Gauss+rand(1,N);
end

Gauss=Gauss-6;
figure;plot(Gauss,1:N,'*')

%------判断分布是否为Gauss分布-----------------
Num=501;                                                %区间大小
Max=max(abs(Gauss))+10^-9;                       %边界
y=zeros(1,Num-1);
x=linspace(-Max,Max,Num);   %-Max,Max间分为501个点,500段
h=x(2)-x(1);
for i=1:length(Gauss)
    index=fix((Gauss(i)+Max)/h)+1;
    y(index)=y(index)+1;
end
figure;bar(x(1:end-1),y);                       %生成数绘图

Von Neumanm舍选法

考虑 $[a,b]$区间上的有界分布 $w(x)$,$w(x)\le c\equiv w’(x)$,则可如下生成按 $w(x)$分布的随机数:

  • 生成 $[a,b]$内的均匀分布随机数$x$ $$ x=(b-a)\mathrm{rand}(0,1)+a $$
  • 生成 $[0,c]$内的均匀分布随机数$y$ $$ y=c\mathrm{rand}(0,1) $$
  • 若 $y\le w(x)$,接受随机数 $x$w为所需 $w(x)$分布的随机数,否则重新抽取 $(x,y)$
%利用Von Neumann舍选法产生随机数
a=0;b=1.0;
h=0.001;
w=@(x) 6/5*(1-0.5*x.^2);%随意选取的分布
N=5*10^6;
xx_s=Von_Neumann(w,a,b,h,N);
plot(xx_s(1:N),1:N,'*')

%---------统计随机数的分布------------
M=1000;
yy1=zeros(1,M);
h1=(b-a)/M;
xx1=a:h1:b;
for i=1:length(xx_s)
    index=fix(xx_s(i)/h1)+1;
    yy1(1,index)=yy1(1,index)+1;
end
figure;bar(xx1(1:end-1),yy1);                       %生成数绘图
S=interg(a,b,w);
yy1=yy1/N/h1*S; %因为yy1/N/h1在[a,b]上的积分为1,为了与w比较,乘以其在[a,b]上的积分S
figure;plot(xx1(1:M),yy1,'r*-');title('Von Neumann舍选法产生的随机数分布');
hold on
plot(xx1(1:M),w(xx1(1:M)),'b')
legend('Von Neumann舍选法产生的随机数分布','精确分布')

%生成步长为$h$的[a,b]区间N个按w(x)分布的随机数函数
function xx_s=Von_Neumann(w,a,b,h,N)
if nargin < 5        %nargin是用来判断输入变量个数的函数 
    h = 10^-4; %步长标准
end
x=a:h:b;
y_m=max(w(x))*1.001;%选择的w'
i=0;     
n=0;
xx_s=zeros(N,1);
while i<N
    xx=(b-a)*rand(1,1)+a;%产生[a,b]区间上的均匀分布的随机数
    yy=y_m*rand(1,1);
    n=n+1;   %统计产生了多少次随机数
    if yy<=w(xx) %舍选法的判断标准
        i=i+1;
        xx_s(i)=xx; 
    end
end
end

function S=interg(a,b,w) %w函数在[a,b]上的积分
    n=10000;
    h=(b-a)/n;
    xx_h=a:h:b;
    ww=w(xx_h);
    S=(4*sum(ww(2:2:n))+2*sum(ww(3:2:n-1))+ww(1)+ww(n+1))*h/3; %simpson积分公式
end

Metropolis算法

Metropolis算法与辐射原理一致,设变量序列 $X\sim w(X)$,应决定 $X_n$的下一点 $X_{n+1}$点生成。

  • 将$w(X)$类比为能量,若$X_t$相对于$X_n$处于高能级, 即 $w(X_t)>w(X_{n})$,则 $X_t\to X_n$的自发辐射概率为1,$X_t$总是可接受的;
  • 若$X_t$相对于$X_n$处于低能级, 即 $w(X_t)<w(X_{n})$,则$X_t\to X_n$的受激辐射概率为 $r=\frac{w(X_t)}{w(X_n)}$,仅有概率$r$使得$X_t$是可接受的;

一般严格算法如下:

  • 取 t=0对应无迭代初始状态;
  • 利用先验分布 $\pi^{(0)}$生成初始元素 $x_0$;
  • 进行如下循环直到 $t=M$,$M$为采样数;
    • $t=t+1$;
    • 利用建议分布 $q(x\mid x_{t-1})$生成建议点 $x*$;
    • 计算接受概率 $\alpha = \mathrm{min}\left(1,\frac{p(x^*)}{p(x^{(t-1)})}\right)$
    • 生成均匀随机数 $u\sim \mathrm{rand}(0,1) $
    • 若 $u\le \alpha$,则接受建议点 $x_t=x*$;
    • 否则 $x_{t}=x_{t-1}$

通常取 $\pi^{(0)}\sim N(0,1)$,而 $q(x_t\mid x_{t-1})\sim N(x_{t-1},1)$.


clear; clc;
close all;

N=50000;
a=0;
b=10;
w = @(x) (1 + x.^2).^-1;
xx=mymetro(w,N);
figure;
histogram(xx,200,'Normalization','pdf');%绘制 x 的概率密度函数估算值。


Num=501;                                                %区间大小
Max=max(abs(xx))+10^-9;                       %边界
y=zeros(1,Num-1);
x=linspace(-Max,Max,Num);
h=x(2)-x(1);
for i=1:length(xx)
    index=fix((xx(i)+Max)/h)+1; %判定xx(i)处于哪个子区间,fix为舍去小数取整运算
    y(index)=y(index)+1;          %该子区间的随机数数目+1
end
figure;bar(x(1:end-1),y); 


%精确值绘图
figure,fplot(w,[-Max,Max],'r');
hold on;
S=interg(-Max,Max,w);
y=y/length(xx)/h*S;  %生成的随机数的数目为n(length(xx)),走的总步数为N
plot(x(1:Num-1),y,'*');title('验证随机数分布');
legend('精确分布','随机数分布')
hold off


function S=interg(a,b,w) %w函数在[a,b]上的积分 
    n=10000;
    h=(b-a)/n;
    xx_h=a:h:b;
    ww=w(xx_h);
    %S=sum(w(xx_h).*(b-a)/n)-w(a)*(b-a)/2/n-w(b)*(b-a)/2/n; %梯形算法
    S=(4*sum(ww(2:2:n))+2*sum(ww(3:2:n-1))+ww(1)+ww(n+1))*h/3; %simpson积分公式
end

function x=mymetro(w,N)
    x=zeros(1,N);
    x(1)=randn;%标准正态分布生成初始随机数
    t = 1; % 抽样编号
    while t<N
        t=t+1;
        %建议采样
        xs= normrnd(x(t-1) ,1); % 按照建议抽样函数进行采样
        r=min([1, w(xs)/w(x(t-1))]); % 接受概率
        %判断是否接受
        u = rand; % Metropolis 采样的核心部分
        if u < r
            x(t) = xs;
        else
            x(t) = x(t-1);
        end  
    end
end
Orbifold
Orbifold
Undergraduated Student

I am an undergraduated students majoring in physics.