蒙特卡洛理解與python實現(xiàn)1-如何生成隨機變量

蒙特卡洛系列算法需要進行隨機變量的采樣,先理解如何生成(仿真)隨機變量(這里只討論連續(xù)型隨機變量的生成)。

逆變換法(Inverse Transform Method)

  • 原理:如果我們有一個隨機變量U符合[0,1]均勻分布,并且X=F^{-1}(U),那么X就是一個分布函數(shù)(CDF)為F的隨機變量。也就是說如果我們需要生成符合標分布F的隨機變量X,先用均勻分布生成隨機變量U,將其輸入F^{-1},得到的函數(shù)輸出結果就是我們需要的X。

一句話總結:嚴格單調遞增(保證有逆函數(shù))的累積分布函數(shù)服從均勻分布

image.png
  • 證明:見參考文獻

  • 算法


    image.png
  • 算法實踐:采樣符合logistic分布的隨機變量X

  1. logistic分布的CDF是F(x) = \frac{e^x}{1+e^x}, x \in R
    求其逆函數(shù)得F^{-1}(x) = log\frac{x}{1+x}
  2. 給定u \sim unif(0,1),則X = F^{-1}(u) = log\frac{u}{1+u} \sim logistic
#下面所有代碼均引用這兩個包
import numpy as np
import matplotlib.pyplot as plt  

def inverse_transform():
    results = []
    N = 1000
    for i in range(N):
        u = np.random.uniform(0,1)
        x = np.log(u / (1-u))
        results.append(x)
    return results

results_inv = inverse_transform()
plt.hist(results_inv,bins=100,color='green')
plt.show()
image.png
  1. 理論驗證

P(log(\frac{u}{1-u})\leq x) = P(\frac{u}{1-u} \leq e^x) = P(u \leq \frac{e^x}{1+e^x} ) = F_{U}( \frac{e^x}{1+e^x} ) =\frac{e^x}{1+e^x} = F(X)

其中F_U(u)是指u的均勻分布的CDF,F(u) = \frac{u-a}{b-1} , u = \frac{e^x}{1+e^x}\in (0,1)

對于另外一些隨機變量,比如正態(tài)分布,F^{-1}不可求,需要用其他方法,
主要有構成法、Box-Muller法、接受-拒絕法

Box Muller 方法 -僅針對正態(tài)分布

  • 原理:如題意描述,這個聯(lián)合隨機分布(X,Y)是一個二元正態(tài)分布,其邊緣分布 X,Y是是兩個獨立的標準正態(tài)分布N(0,1)
    image.png
  • 證明:略
  • 算法:python中默認的正態(tài)分布生成方法即是這個


    image.png

其中包含了 --》如何利用逆變換法生成符合指數(shù)分布的隨機變量T:

假設 T\sim Expo(\lambda) 則有F(t) = 1-e^{-\lambda t}, T = F^{-1}(u) =-\frac{1}{\lambda} *ln(1-u) ,由于u\sim unif(0,1), 則1-u \sim unif(0,1),所以算法中對于T\sim Expo(1)直接生成-lnU

-算法實踐:利用box-muller算法生成標準正態(tài)分布

# Box-Muller  
# Box-Muller  
def box_muller():
    results = []
    N = 1000
    for i in range(N):
        u = np.random.uniform(0, 1, 2) #同時生成2個符合【0,1】均勻分布的隨機變量【u1,u2】
        x = np.cos(2*np.pi*u[0])*np.sqrt(-2*np.log(u[1]))
        y = np.sin(2*np.pi*u[0])*np.sqrt(-2*np.log(u[1]))
        results.append(x) #采樣x、y中任意一個即可
    return results

results_boxmuller = box_muller()
plt.hist(results_boxmuller,bins=100,color='green')
plt.show()
image.png

接受拒絕法(Acceptance-Rejection Algorithm)

  • 原理:如果直接生成目標p分布不容易生成,可以先生成容易得到的q分布,再利用接受拒絕法得到p。
  • 證明:見參考文獻
  • 算法:


    image.png
  • 算法實踐:利用接受拒絕法從指數(shù)分布Expo(1)中生成標準正態(tài)分布N(0,1)

求出c:

  1. Expo(1)的概率密度函數(shù)(PDF)為q(x)=e^{-x},x\geq0
  2. 假設Z \sim N(0,1),目標分布為p(x)=|Z|\sim \frac{2}{\sqrt{2\pi}} e^{-0.5x^2},x\geq 0 (因為指數(shù)分布的定義中x\geq0,所以先生成標準正態(tài)分布的絕對值)
  3. \sup_{x} \frac{p(x)}{q(x)} = \sup_{x} \sqrt{\frac{2}{\pi}} e^{x-0.5x^2} = \sqrt{\frac{2e}{\pi}}
  4. c = \sqrt{\frac{2e}{\pi}}
    其中sup是上確界的意思,sup和max都是定義在實數(shù)集的函數(shù),不同點在于sup是對這個集合取上確界,max是取最大值,最大值存在時,最大值就是上確界

算法過程:

  1. 使用逆變換法生成指數(shù)分布 y\sim q\sim expo(1)
  2. 生成均勻分布u\sim unif(0,1)
  3. 代入u\leq \frac{p(y)}{cq(y)}u\leq e^{-0.5(y-1)^2}
    if u\leq e^{-0.5(y-1)^2}, x = y
  4. 得到 x\sim |Z|之后,令
    \begin{equation} Z= \begin{cases} x& p=0.5 \\ -x& p=0.5 \end{cases} \end{equation}Z\sim N(0,1)
def acc_rej():
    results = []
    N = 10000
    for i in range(N):
        #先生成符號q分布即指數(shù)分布的隨機變量y
        #u = np.random.uniform(0,1)
        #y = -np.log(1-u) 利用逆變換法生成指數(shù)分布
        y = np.random.exponential(1) #直接利用numpy中的函數(shù)生成指數(shù)分布
        u = np.random.uniform(0,1)
        if u <= np.exp(-0.5*(y-1)**2):
            x = y
            z = np.random.choice([x,-x],size = 1,p=[0.5,0.5])
            results.append(z[0]) #z為numpy數(shù)組 取出其中的value
    return results
     
results_accrej = acc_rej()
plt.hist(results_accrej, bins=100, color='green')
plt.show()
  • 算法實踐2:利用接受拒絕法從q:Unif(0,1)中生成p:Beta(2,2)
  1. Beta分布的PDF: p(x,\alpha,\beta) = \frac{1}{B(\alpha,\beta)}x^{\alpha-1}(1-x)^{\beta-1}
    其中的B為beta函數(shù)\mathrm{B}(a, b)=\int_{0}^{1} x^{a-1}(1-x)^{b-1} \mathrmu0z1t8os x
  2. 代入得p(x,2,2) = -6x^2+6x, 均勻分布q(x)=1,則c \geq \sup_{x} \frac{p(x)}{q(x)} = \sup_{x}( -6x^2+6x) = 1.5取c=1.5
  3. 將c代入,得u\leq \frac{p(y)}{cq(y)} = -4y^2+4y
#用均勻分布生成beta(2,2)分布x
def acc_rej():
    results = []
    N = 10000
    for i in range(N):
        y = np.random.uniform(0,1) #q分布
        u = np.random.uniform(0,1)
        if u <= (-4)*y**2+4*y:
            x = y
            results.append(x)
    return results
     
results_accrej = acc_rej()
plt.hist(results_accrej, bins=100, color='green')
plt.show()
  • 接受拒絕法中隱含的tradeoff
    如果我們選擇的分布q越接近p,則c越接近于1,因此生成的隨機變量y越容易被接收,那么acc-rej算法所需要的迭代次數(shù)將會減少,從而導致計算量減小。
    但是,如果q足夠接近p,那么采樣分布q也變得困難(之所以使用接收拒絕法正是因為難以采樣分布p)因此如何平衡容易采樣的分布q和足夠小的c是關鍵。一方面,我們想要c足夠小,接近1以減小計算量,另一方面我們又希望q容易采樣。

逆變換法 vs 接受拒絕法

  • 逆變換法是在CDF上操作,需要CDF逆函數(shù)可求
  • 接受拒絕法是在PDF上操作
    • 使用該方法,對于要生成的目標p分布不需要進行歸一化,算法本身是自我歸一化的(self-normalizing)
    • c\geq 1

參考文獻

  1. http://www.columbia.edu/~mh2078/MonteCarlo.html 中的第一講Generating Random Variables and StochasticProcesses。里面的課件和notes給了很多詳細的證明過程,以及其他的內容如何生成多維的隨機變量、離散的隨機變量等。
  2. https://cosx.org/2015/06/generating-normal-distr-variates/ 作者總結了生成正態(tài)分布的各種方法,包含相關證明。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容