美文网首页
蒙特卡洛理解与python实现2

蒙特卡洛理解与python实现2

作者: _龙雀 | 来源:发表于2020-03-26 16:08 被阅读0次

蒙特卡洛定义

模拟是指把某一现实的或抽象的系统的某种特征或部分状态, 用另一系统(称为模拟模型)来代替或模拟。 为了解决某问题, 把它变成一个概率模型的求解问题, 然后产生符合模型的大量随机数, 对产生的随机数进行分析从而求解问题, 这种方法叫做随机模拟方法, 又称为蒙特卡洛(Monte Carlo)方法。

蒙特卡洛方法的名字来源于摩纳哥的一个城市蒙特卡洛,该城市以赌博业闻名,而蒙特卡洛方法正是以概率为基础的方法,第一次提出是在二战时期曼哈顿计划制造第一代原子弹的项目中。蒙特卡洛方法是一系列符合该定义算法的统称,而不是一个算法。

蒙特卡洛主要有三个用处:

  • 近似求解积分(蒙特卡洛积分法)
  • 密度估计:通过采样逼近目标分布
  • 优化函数:找到能使目标函数最大化或最小化的样本

初识蒙特卡洛- 随机投点法计算圆周率

投点法是最朴素的蒙特卡洛思想,与几何概率类似。


image.png

算法实践:

def estimate_pi():
    N = 10000
    count = 0
    for i in range(N):
        x = np.random.uniform(0,1)
        y = np.random.uniform(0,1)
        if x**2+y**2 <= 1:
            count += 1
    return (count/N)*4

标准蒙特卡洛-平均值法

英文称呼有以下几种:standard monte carlo,directed monte carlo, standard sample average 。
原理是利用强大数定理,n足够大时,样本的均值等于随机变量的期望。

求积分

假设p(x)是目标分布,我们要计算\int_a^b p(x) dx, 则使用标准蒙特卡洛法估算期望
E_p[h(X)] = \int_X h(x) p(x) dx

\bar{h_n} = \frac{1}{n} \sum_{i=1}^n h(x_i)
其中x_i \sim p,按照强大数定理,\hat h_n依概率为1收敛到E_p[h(x)]
通常X\sim unif(0,1), h(x) = \frac{x-0}{1-0}

image.png
  • 算法实践:利用平均采样法求I = \int_0^1 e^x \,dx = e-1 \approx 1.718
  1. 生成随机变量U
  2. 采样N次 代入\hat I = \frac{1}{N} \sum_{i=1}^N e^{U_i}
def average_sample():
    N = 1000
    x_hat = []
    for i in range(N):
        u = np.random.uniform(0,1)
        x_hat.append(np.exp(u))
    return sum(x_hat)/N

重要性采样

使用标准蒙特卡洛法有时候生成的结果方差比较大,重要性抽样能够有效的减小方差。
标准的蒙特卡洛法是E_p[h(X)] = \int_X h(x) p(x) dx
加上一个重要性分布q(x),重写以上公式得
E_p[h(x)] \ = \ \int_X h(x) \frac{p(x)}{q(x)} q(x) dx \ = \ E_q\left[ \frac{h(X) p(X)}{q(X)} \right]
我们可以得到新的估计
\hat{h_n} = \frac{1}{n} \sum_{i=1}^n \frac{p(x_i)}{q(x_i)} h(x_i)
其中x_i\sim q
根据强大数定理SLLN,\hat h_n依概率为1收敛到E_p[h(x)]

self-normlized重要性采样

有时不仅p(x)很难直接抽样,而且p(x)本身未知, 只能确定到差一个常数倍的\hat p(x) = c*p(x),计算c一般很困难。定义w(x) = \frac{p(x)}{q(x)},则得到新的蒙特卡洛积分公式
\hat{h_n} = \frac{\frac{1}{n} \sum_{i=1}^n w(x_i) h(x_i)}{\frac{1}{n}w(x_i)}

如何选择一个好的重要性分布q- Tilted Densities方法

Tilted Densities方法利用moment generating function ,构造如下:
q(x)=\frac{e^{t x} p(x)} {\int e^{t x} p(x) d x}, t \in R

  • 算法实践 利用重要性采样法求I = \int_0^1 e^x \,dx = e-1 \approx 1.718
  1. 对被积函数p(x)做泰勒展开得e^x = 1 + x + \frac{x^2}{2!} + \cdots
  2. 取重要性分布 q(x)=c(1+x) = \frac{2}{3}(1+x)
  3. 利用逆变换法产生q(x)
    q(x)的分布函数Q(x)求逆得 Q^{-1}(y) = \sqrt{1+3y}-1, \ 0<y<1
    生成随机变量U_i \sim Unif(0,1),令X_i = \sqrt{1+3U_i}-1
  4. 则重要抽样法的积分公式为
    \hat I = \frac{1}{N}\sum_{i=1}^N \frac{e^{X_i}}{\frac{2}{3}(1+X_i)}
def importance_sample():
    N = 1000
    x_hat = []
    for i in range(N):
        x = np.random.uniform(0,1) #以0-1均匀分布生成随机数x
        x = np.sqrt(1+3*x) - 1 #将x代入,生成PDF为q(x)的分布
        y = np.exp(x) / ((2/3)*(1+x)) #以p(x)/q(x)采样
        x_hat.append(y) 
    return sum(x_hat)/N   #对所有仿真结果求均值 
  • 算法实践2:假设X\sim N(0,1), 估计概率c = P(X >\alpha)的值

引入指示变量I,则有E(I(x_k > \alpha)) = P(x_k > \alpha)

  1. 使用标准蒙特卡洛方法
    取N个样本 则 \hat c =\frac{1}{N}\sum_{x=k}^NI(x_k > \alpha), x_k\sim N(0,1)
  2. 使用重要性抽样方法
    其中p\sim N(0,1), p(x)=\frac{1}{\sqrt{2 \pi }} e^{-0.5x^2},我们选择q \sim N(u,1),q(x)=\frac{1}{\sqrt{2 \pi }} e^{-0.5(x-u)^2}
    \hat c_{is} = \frac{1}{N}\sum_{x=k}^NI(x_k > \alpha) \frac{p(x_k)}{q(x_k)} = \frac{1}{N}\sum_{x=k}^NI(x_k > \alpha) e^{0.5u^2-ux_k}
    其中x_k\sim N(u,1),当u=\alpha时候q(x)是一个合理的选择
def average_sample():
    count = 0
    for i in range(1000):
        x_k = np.random.normal(0,1)
        if x_k > 8:
            count += 1
    return count/1000

def importance_sample():
    N = 50000
    alpha = 8
    result = []
    for i in range(N):
        x = np.random.normal(alpha,1) #q分布 N(alpha,1)
        if x > alpha:
            result.append(np.exp(0.5*alpha**2 - alpha*x))
    return sum(result)/N

参考文献

  1. http://www.columbia.edu/~mh2078/MonteCarlo.html关于重要性采样这里有更数学化的证明过程以及其他选择q(x)的方法。

  2. 北京大学统计计算讲义-李东风 本文中部分例题来源于此,里面提供了关于重要性采样如何减小方差的理论验证过程。

  3. https://people.duke.edu/~ccc14/sta-663/MonteCarlo.html
    这里提供了蒙特卡洛方法的纯numpy运算实现,不用for循环,代码更简洁,但没那么好理解。

相关文章

网友评论

      本文标题:蒙特卡洛理解与python实现2

      本文链接:https://www.haomeiwen.com/subject/gtycuhtx.html