蒙特卡洛模擬方法

2021-01-13 日月生明

       花費兩天的時間去幫老師研究課題,完成那一刻瞬間感覺自己學到的數學知識很有用。於是想著以一種方式去記錄這次算法。思來想去寫了這個公眾號,作為第一篇自我感覺有價值的文章,我會一點一滴的去寫。但是由於老師的課題需要發表論文,所以本文不會給出具體關於課題的任何代碼。但是會用python去構思基本的東西出來。我希望此文可以記錄思想,整理筆記、知識,並將其中承載的價值傳播給他人。 
在本文中您可以學習到以下幾點知識

蒙特卡洛定積分算法原理講解(公式篇)

python實現算法(代碼篇)

蒙特卡洛算法起源

       蒙特卡羅方法於20世紀40年代美國在第二次世界大戰中研製原子彈的「曼哈頓計劃」計劃的成員S.M.烏拉姆和J.馮·諾伊曼首先提出。數學家馮·諾伊曼用馳名世界的賭城—摩納哥的Monte Carlo—來命名這種方法,為它蒙上了一層神秘色彩。在這之前,蒙特卡羅方法就已經存在。1777年,法國Buffon提出用投針實驗的方法求圓周率∏。這被認為是蒙特卡羅方法的起源。 
很簡單的一個小例子,在長寬都為1cm的正方形中有一個最大圓,如何用數理統計的思想去求解這個面積呢?實際上我們可以在正方形中扔豆子,扔很多很多次(n),然後計算圓內豆子和總豆子的比例,再乘以正方形面積,當n趨近於無窮大時,這時候正方形面積乘以豆子比例在理想情況下就是圓的面積了。基於這個思想,我們可以思考一下,如何去計算一個一維積分呢?

蒙特卡洛求解定積分原理(公式篇)

一維積分: 

     在x的定義域[0,1]中均勻隨機取點,該均勻分布的隨機變量記為η1,定義一個隨機變量η為:

則顯然有: 

     η1的期望值等於積分I。只要抽取足夠多的隨機點,即隨機點的點數足夠多大時,n的平均值f(ξ):

就是積分Ι的無偏估計值。 
η1的方差為: 

      顯然V{η1 }依賴被積函數f(x)在積分域上的方差。當f(x)在x的定義域內變化曲率較小(平坦),就是和I的差值較小時,方差也小;反之,方差越大。 
如果想減小積分估計值得差值,就需要減小被積函數在積分區域上的方差。一個很重要的思想——重要抽樣法: 
將f(x)的方差吸收到一個特定函數g(x)中。假設f*(x)=f(x)/(g(x)在定義域內極其平緩,那麼積分公式變為: 

若選取η'為服從概率密度函數g(x)的函數f*(x)的抽樣值。則可以得到:

因此它的平均值為: 

給出一個I的無偏估計值。這時的方差為:

在實際計算中,方差可以通過以下方程得到: 

      方程中角型括號表示對括號內所有可能的[0,1]區間,按g(x)分布的隨機坐標數序列{x_i }對應的數值求平均值。方程右邊第一項對{f*²(x_i)}求平均記為a,第二項表示求{f*(x_i)}的平均值的平方,記為b。上面方程可以推導得到: 

    由此我們看出其誤差平方與f*在[0,1]區間的方差成正比,並且σ∝(1/√n)。這與中心極限定理所得到的的結果一致。

利用python計算定積分實例(代碼篇)

如下圖所示: 

利用蒙特卡洛計算

python代碼如下所示:

import numpy as npimport matplotlib.pyplot as plt def f(x):  return x**2 + 4*x*np.sin(x) def intf(x):   return x**3/3.0+4.0*np.sin(x) - 4.0*x*np.cos(x)a = 2;  b = 3; N= 10000X = np.random.uniform(low=a, high=b, size=N) Y =f(X)  Imc= (b-a) * np.sum(Y)/ N;exactval=intf(b)-intf(a)print("Monte Carlo estimation=",Imc, "Exact number=", intf(b)-intf(a))Imc=np.zeros(1000)Na = np.linspace(0,1000,1000)exactval= intf(b)-intf(a)for N in np.arange(0,1000):  X = np.random.uniform(low=a, high=b, size=N)   Y =f(X)    Imc[N]= (b-a) * np.sum(Y)/ N;   plt.plot(Na[10:],np.sqrt((Imc[10:]-exactval)**2), alpha=0.7)plt.plot(Na[10:], 1/np.sqrt(Na[10:]), 'r')plt.xlabel("N")plt.ylabel("sqrt((Imc-ExactValue)$^2$)")plt.show()

實驗成圖如下:

      從上圖可以看出隨著實驗次數的不斷增加,計算的誤差也越來越小。由此想要提高精確度有兩個方法:

增加實驗次數: 
隨著實驗次數的不斷增加,計算機計算的時間也越來越長,不是很符合實際情況;

重要採樣方法 
重要採樣方法的特點在於,它不是從給定的過程的概率抽樣,而是修改的概率分布抽樣,使對模擬結果有重要作用的事件更多多次出現,從而提高抽樣概率,減少花費在對模擬結果無關緊要的事件上的計算時間。比如在區間[a,b]上求g(x)的積分,若採用均勻抽樣,在函數值g(x)比較小的區間內產生的抽樣點跟函數值較大處區間內產生的抽樣點的數目接近,顯然抽樣效率不高,可以將抽樣概率密度函數改為f(x),使f(x)與g(x)的形狀相近,就可以保證對積分計算貢獻較大的抽樣值出現的機會大於貢獻小的抽樣值,即可以將積分改為:

x是按照抽樣概率密度f(x)抽樣獲得的隨機變量,顯然在區間[a,b]上應該有: 

      因此,可以容易將積分值I看成是隨機變量Y=g(x)/f(x)的期望值,式子中服從概率密度為f(x)的採樣點: 

     下面的例子採用正太分布f(x)來近似g(x)=xsinx,並根據正太分布來選取採樣值區間為[0,π]上的積分: 

python代碼如下所示:

 from scipy import statsfrom scipy.stats import normimport numpy as npimport matplotlib.pyplot as pltmu = 2;sig =.7;f = lambda x: np.sin(x)*xinfun = lambda x: np.sin(x)-x*np.cos(x)p = lambda x: (1/np.sqrt(2*np.pi*sig**2))*np.exp(-(x-mu)**2/(2.0*sig**2))normfun = lambda x: norm.cdf(x-mu, scale=sig) plt.figure(figsize=(18,8)) xmax =np.pi xmin =0N =1000x=np.linspace(xmin, xmax, 1000)plt.subplot(1,2,1)plt.plot(x, f(x), 'b', label=u'Original $x\sin(x)$')plt.plot(x, p(x), 'r', label=u'Importance Sampling Function: Normal')plt.xlabel('x')plt.legend()Iexact = infun(xmax)-infun(xmin)print(Iexact)Ivmc = np.zeros(1000)for k in np.arange(0,1000):  x = np.random.uniform(low=xmin, high=xmax, size=N)  Ivmc[k] = (xmax-xmin)*np.mean(f(x)) Iis = np.zeros(1000)for k in np.arange(0,1000):    xis = mu + sig*np.random.randn(N,1);  xis = xis[ (xis<xmax) & (xis>xmin)] ;    normal = normfun(np.pi)-normfun(0)     Iis[k] =np.mean(f(xis)/p(xis))*normal  plt.subplot(1,2,2)plt.hist(Iis,30, histtype='step', label=u'Importance Sampling');plt.hist(Ivmc, 30, color='r',histtype='step', label=u'Vanilla MC');plt.vlines(np.pi, 0, 100, color='g', linestyle='dashed')plt.legend()plt.show()

實驗效果圖如下:

     從圖中可以看出xsin⁡x的圖像與正太分布圖像很接近,因此在曲線峰值採樣點的數量要比曲線上其他低的位置多。精確計算的結果為π,從上面的右圖可以看出:兩種計算方法計算定積分1000次,精確靠近π=3.1415處的結果最多,離精確值越遠數目越少,顯然符合常規。但傳統的方法(紅色直方圖)計算出的積分值的差明顯比採用重要採樣法(藍色直方圖)要大。因此採用重要採樣法計算可以降低方差,提高精度。另外需要主要的是:關於f(x)的選擇會對計算結果的精度產生影響,當選擇的函數f(x)與g(x)相差較大時,計算結果的方差也會增大。

到此為止,蒙特卡洛算法從原理到實驗講述完畢,不知道我講明白沒有呢?

我們一直都在努力前行,將科學與現實聯繫在一起,將藝術與生活緊密結合

相關焦點

  • 蒙特卡洛模擬方法及應用案例
    是把概率現象作為研究對象的數值模擬方法。是按抽樣調查法求取統計值來推定未知特性量的計算方法。蒙特卡羅法作為一種計算方法,是由美國數學家烏拉姆與美籍匈牙利數學家馮·諾伊曼在20世紀40年代中葉,為研製核武器的需要而首先提出來的。蒙特卡羅是摩納哥的著名賭城,該法為表明其隨機抽樣的本質而命名,故適用於對離散系統進行計算仿真試驗。
  • 什麼是蒙特卡洛模擬?
    蒙特卡洛方法正是以概率為基礎的方法,因為偶然性和隨機結果是建模技術的核心,就像輪盤賭,骰子和老虎機等遊戲一樣。蒙特卡洛方法(Monte Carlo method),也稱統計模擬方法,是二十世紀40年代中期由於科學技術的發展和電子計算機的發明,而提出的一種以概率統計理論為指導的數值計算方法。其使用隨機數(或更常見的偽隨機數)來解決很多計算問題的方法。
  • 蒙特卡洛模擬算法|公開課3
    本篇是「微慕課」公開課系列第3講——蒙特卡洛模擬算法蒙特卡洛(Monte Carlo)模擬方法是一種廣受好評的算法,
  • 蒙特卡洛模擬(Monte Carlo Simulation)
    一、介紹蒙特卡洛模擬是一種統計學方法,用來模擬大量的數據。
  • 蒙特卡洛方法到底有什麼用?
    蒙特卡洛方法(Monte Carlo method,也有翻譯成「蒙特卡羅方法」)是以概率和統計的理論、方法為基礎的一種數值計算方法,將所求解的問題同一定的概率模型相聯繫,用計算機實現統計模擬或抽樣,以獲得問題的近似解,故又稱隨機抽樣法或統計試驗法。上述就是蒙特卡洛方法的基本概念,比較抽象,下面結合實際工作中的理解,談一談對蒙特卡洛方法的一些認識。
  • 蒙特卡洛模擬(Python)深入教程
    蒙特卡洛模擬使我們能夠看到決策的所有可能結果,並評估風險影響,從而在不確定的情況下更好地做出決策。在本文中,我們將通過五個不同的例子來理解蒙特卡羅模擬方法。在這個例子中,我們將使用蒙特卡羅方法迭代地模擬拋硬幣5000次,以找出為什麼頭部或尾巴的概率總是1/2。如果我們重複拋硬幣很多很多次,那麼我們可以在概率值的準確答案上獲得更高的精確度。在這個例子中,我們將使用Monte-Carlo方法反覆模擬拋硬幣5000次,以找出頭部或尾部的概率始終是1/2的概率。圖2:正面和反面,數學表示。
  • 蒙特卡洛方法在美式期權定價中的應用
    蒙特卡洛方法是以概率和統計理論方法為基礎的一種計算方法,利用隨機數(實際應用中通常為偽隨機數)來產生隨機的基於一定分布假設的數字序列,進而解決各種計算問題。通過對問題的結果分布進行假設和擬合,利用電子計算機實現統計模擬或抽樣,以獲得問題的近似解。為象徵性地表明這一方法的概率統計特徵,故借用賭城蒙特卡洛命名。
  • 一文了解AlphaGo中蒙特卡洛方法的由來與發展
    ,主要是為核武器的研發和製作而工作,蒙特卡洛方法以概率統計為理論指導,由於一個簡單的隨機數發生器一輪盤賭,外加烏拉姆的叔叔十分嗜好賭博且經常在蒙特卡洛賭場輸錢,方法便以摩納哥的馳名世界的賭城-蒙特卡洛來命名,蒙特卡洛方法的名稱和系統開發由此開始。
  • 蒙特卡洛模擬的簡單例子
    他的方法簡單得實在是出人意料:它在金屬板上切出旋輪線的形狀,拿到秤上稱了稱,發現重量正好是對應的圓形金屬片的三倍。「稱重」是對蒙特卡羅模擬法最形象的解釋。 蒙特卡洛模擬我們首先把旋輪線放在坐標系中:旋輪線的方程為:x=r*(θ-sinθ)y=r*(1-cosθ)旋輪線內切於一個矩形
  • 無需數學知識:快速了解馬爾可夫鏈蒙特卡洛方法
    這時,我們就需要使用MCMC方法。MCMC方法允許我們對後驗分布的形狀進行估計,從而解決這類無法直接計算的問題。這裡再次強調,MCMC的全稱即為馬爾可夫鏈蒙特卡洛方法。為了理解其工作原理,我將首先介紹蒙特卡洛模擬,而後再討論馬爾可夫鏈概念。
  • 蒙特卡洛模擬算法的探討與應用
    附錄一  蒲豐投針實驗與蒙特卡洛算法的相關代碼1.%以P開頭為畫圖程序,具體詳見附錄  13.Pmyanov(n,myanov,is);  14.Pmyerr(n,myerr,is);  15.Prep(mypi_n);  16.is = 0;  17.Pmyanov(n,myanov,is);  18.Pmyerr(n,myerr,is);  ……附錄二  蒙特卡洛模擬結果方差分析的相關代碼匯總
  • Python學習第130課——蒙特卡洛模擬隨機遊走
    現在我們用蒙特卡洛模擬計算一下,醉漢在不同的條件下打車回家的概率。我們先定義幾個參數。how_many_steps,表示醉漢走多少步數算完成一次隨機遊走。foot_limit,表示醉漢超過出發的原點多少米就不走了,要打車回家。how_many_simulations,表示我們模擬多少次醉漢遊走的過程。
  • 一份數學小白也能讀懂的「馬爾可夫鏈蒙特卡洛方法」入門指南
    在貝葉斯經典方法中,馬爾可夫鏈蒙特卡洛(Markov chain Monte Carlo/MCMC)尤其神秘,其中數學很多,計算量很大,但其背後原理與數據科學有諸多相似之處,並可闡釋清楚,使得毫無數學基礎的人搞明白 MCMC。這正是本文的目標。那麼,到底什麼是 MCMC 方法?
  • 【學習心得032】期權定價之蒙特卡洛模擬法
    期權定價的方法主要有蒙特卡洛模擬以及二叉樹的方法,我們首先介紹使用蒙特卡洛模擬的方法。
  • 自學習蒙特卡洛三部曲推動凝聚態量子領域發展
    蒙特卡洛方法(Monte Carlo method),也稱統計模擬方法,是二十世紀四十年代中期由於科學技術的發展和電子計算機的發明,而被提出的以概率統計理論為指導的一類非常重要的數值計算方法
  • 蒙特卡洛算法在程序化研究中簡單應用
    可以從CPI、PPI、貨幣發行量等宏觀經濟指標出發,建立擇時交易系統,這種方法為多為機構應用。    微觀方面,筆者認為,可以講傳統的指標組合方法進行升華,引入在物理數學中成熟的數學模型,改進傳統的程序化交易模型,如運用數值計算中的蟻群算法和模擬退火算法等,本文介紹的也是數值計算中的蒙特卡洛算法。
  • 詳解蒙特卡洛方法:這些數學你搞懂了嗎?
    該系列文章現已介紹了賭博機問題、馬爾可夫決策過程和蒙特卡洛方法。本文是對其中蒙特卡洛方法文章的編譯。引言蒙特卡洛模擬(Monte Carlo simulations)得名於摩納哥的賭城,因為機率和隨機結果是這種建模技術的核心,所以它就像是輪盤賭、骰子和老虎機等遊戲一樣。
  • 簡潔清晰解釋馬爾可夫鏈蒙特卡洛方法
    有三種解釋MCMC的方法: 初級:MCMC允許我們利用計算機進行貝葉斯統計。 中級:MCMC是一種可以找到我們感興趣的參數的後驗分布的方法。具體來說,這種類型的算法以依賴Markov屬性的方式生成蒙特卡羅模擬,然後以一定的速率接受這些模擬以獲得後驗分布。 高級:完整的統計思想。本文,讓你達到中級水平。讓我們從初級水平開始。什麼是MCMC?
  • 蒙特卡洛梯度估計方法(MCGE)簡述
    其中,對於函數期望類目標問題,最常見的是基於蒙特卡洛採樣的方法。背景知識要了解基於蒙特卡洛採樣的梯度估計方法,首先先了解蒙特卡洛採樣方法和隨機優化方法。MCS 是一種經典的求解積分方法,公式(1)中的問題通常可以用 MCS 近似求解如下:
  • 蒙特卡洛模擬法的實施步驟
    蒙特卡洛模擬法的實施步驟一般分為三步:  (1)分析每一可變因素的可能變化範圍及其概率分布。  (2)通過模擬試驗隨機選取各隨機變量的值,並使選擇的隨機值符合各自的概率分布。為此可使用隨機數或直接用計算機求出隨機數。  (3)反覆重複以上步驟,進行多次模擬試驗,即可求出開發項目各項效益指標的概率分布或其他特徵值。