JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

蒙地卡羅模擬

當一個積分或機率難到無法手算時,你大可直接抽取隨機樣本,讓大數法則替你完成工作。這就是蒙地卡羅:把困難的數學變成簡單的取平均——並且要弄清楚,到底何時可以相信那個答案。

核心點子:困難的數學,簡單的取平均

假設你必須計算某個量 g(X) 的平均,其中 X 是隨機的——比方說一場複雜賭局的期望收益,或一個沒有公式能攻破的積分。上一篇展示了貝氏後驗往往只能知道到一個雜亂的常數倍,而對它做積分,正是我們無法手算的那些東西。蒙地卡羅模擬用一個極其直白的策略回應:與其去解那個積分,不如抽取大量隨機樣本然後取平均。如果你做不出微積分,那就讓骰子替你做。

這就是引擎,而且是你早先的階段就已擁有的。根據「無意識統計學家定律」,我們想要的東西是一個期望值:E[g(X)] 是 g(X) 在 X 的隨機性下的真實平均。根據[[strong-law-of-large-numbers|強大數法則]],若你從 X 的分配中抽取獨立樣本 X_1, ..., X_N,並對它們取 g 的平均,這個樣本平均會隨著 N 增大而收斂到真實期望值。所以食譜是:抽樣、套用 g、取平均。這個估計量就是經驗均值 (g(X_1) + ... + g(X_N)) / N,而它幾乎必然地命中 E[g(X)]。

為什麼叫「蒙地卡羅」?這名字是個戰時的內部玩笑:烏拉姆(Stanislaw Ulam)與馮紐曼(John von Neumann)於 1940 年代在洛斯阿拉莫斯研究中子擴散時,需要一個代號來稱呼他們「用隨機抽樣解物理」的祕密方法,而烏拉姆的叔叔愛在蒙地卡羅賭場賭博。這個輕佻的名字,就此黏在了那個世紀裡最有用的計算點子之一上。每當一個量其實是「喬裝過的期望值」,蒙地卡羅就能攻擊它。

一個具體畫面:用擲飛鏢估計 pi

這個經典的玩具讓整個點子變得看得見。畫一個邊長為 2、以原點為中心的正方形,並在裡面內接一個半徑為 1 的圓。正方形面積為 4,圓面積為 pi,所以圓所覆蓋的正方形比例是 pi / 4。現在把飛鏢均勻隨機地擲進正方形:每支飛鏢落在圓內的機率,恰好就是那個比例 pi / 4。這不過是把幾何機率變成一個我們真能跑的實驗罷了。

於是產生 N 個點 (x, y),其中 x 與 y 各自在 [-1, 1] 上均勻分布,數一數有多少個滿足 x^2 + y^2 <= 1,並構造比例 p-hat = (命中數) / N。根據大數法則,p-hat 會趨向 pi / 4,所以 4 * p-hat 就是 pi 的一個蒙地卡羅估計。擲 1000 支飛鏢,你或許會得到像 3.10 或 3.18 的值;擲一百萬支,你就會穩定地看到 3.14 左右。注意剛剛發生了什麼:一個關於常數 pi 的問題——純粹的確定性數學——竟靠著「數隨機事件」得到了答案。這個逆轉,正是這個方法全部的魔法。

fraction inside circle  =  (area of circle) / (area of square)  =  pi / 4

Monte Carlo estimator   :  p-hat   = (hits) / N
                           pi-hat  = 4 * p-hat   ->  pi   as N -> infinity
擲飛鏢估計 pi:一個幾何比例變成了一次計數,而那次計數又變成了一個數。

它收斂得多快?平方根定律

知道估計在「極限下」是正確的還不夠——我們需要知道在有限的 N 之後它有多接近。這裡[[prob-central-limit-theorem|中央極限定理]]給出精確的回答。蒙地卡羅估計量是 N 個獨立 g(X) 副本的平均,所以若 g(X) 的變異數為 sigma^2,則估計量的變異數為 sigma^2 / N。因此它的標準誤——誤差的典型大小——是 sigma / sqrt(N)。誤差會縮小,但只以「N 的平方根分之一」的速度。

那條平方根定律是實用蒙地卡羅的核心事實,而且發人深省。要把誤差減半,你必須把 N 增為四倍;要再多一位準確的小數(誤差縮小十倍),你需要一百倍的樣本。這就是為什麼我們的 pi 飛鏢估計,即使在 N = 1000 時也還在 3.1 附近搖晃:以這裡的二項變異數計算,標準誤大約是 0.05,所以差個 0.04 完全是家常便飯。不過另一面是真正了不起的:那個 sigma / sqrt(N) 的速率,完全不含維度數。古典的格點積分隨著維度增長需要指數級多的點,但蒙地卡羅的誤差速率在 2 維或 2000 維都一樣。正是這個「與維度無關」的特性,讓它在高維問題上稱霸。

那些隨機數從哪裡來?

蒙地卡羅需要一道樣本之泉,但電腦是確定性的,無法真的擲硬幣。標準的訣竅是從一個主力出發:一個偽隨機數產生器,它產出一長串看起來在 [0, 1] 上均勻、且統計上互相獨立的值,儘管它們其實是由一個固定公式從一個種子生成的。(因為種子與公式都固定,這道串流是完全可重現的——這是個優點,因為它讓你能重跑模擬並除錯。)從那道均勻串流,其他所有分配都被製造出來。

從均勻通往其他任何分配的橋樑,是[[inverse-transform-method|逆轉換法]],它直接從你早先見過的「機率積分轉換」掉出來。若 F 是你想要的累積分配函數、U 在 [0, 1] 上均勻,則 F-inverse(U)——把一個均勻數穿過反 CDF——恰好具有分配 F。對於速率為 lambda 的指數分配,F(x) = 1 - e^(-lambda x),反轉後給出俐落的規則 X = -ln(U) / lambda:一次均勻抽樣就變成一次指數抽樣。對於 CDF 無法以閉合形式反轉的分配——常態分配是著名的例子——則有專門的訣竅,如 Box-Muller 轉換,它把兩個均勻數變成兩個獨立的標準常態數。

讓它更銳利,以及通往統計的橋樑

由於誤差是 sigma / sqrt(N),這裡有兩根槓桿:提高 N,或降低 sigma。提高 N 只是花電腦時間;更聰明的技藝是[[variance-reduction|變異數縮減]]——重新設計估計量,讓同樣的 N 換來更小的 sigma。一個簡單的例子是對偶抽樣:對每個均勻數 U,同時也用它的鏡像 1 - U;當 g 是單調時,這一對估計呈負相關,所以它們的平均比兩次獨立抽樣有更低的變異數。其他方案(控制變量、重要性抽樣、分層)追求的都是同一個目標:保持不偏,縮小離散程度。一個精選的變異數縮減方案,可能免費抵得上把 N 增為一百倍。

  1. 把你的量寫成某個隨機 X 與函數 g 的期望值 E[g(X)]——這是建模步驟。
  2. 從 X 的分配中抽取 N 個獨立樣本 X_1, ..., X_N(先由產生器取均勻數,再用逆轉換或專門方法)。
  3. 取平均:估計值為 (g(X_1) + ... + g(X_N)) / N,根據大數法則它收斂到 E[g(X)]。
  4. 回報不確定性:由樣本估計 sigma,並標出標準誤 sigma / sqrt(N)(由中央極限定理得到的信賴帶)。永遠不要交出一個沒有誤差棒的蒙地卡羅數字。

蒙地卡羅還悄悄地把機率的通常流向反轉過來,因而推開了通往統計的門。平常我們知道模型、去算結果;這裡我們把模型向前跑許多次,以了解那些我們推導不出的性質。完全相同的這一招,驅動著[[bootstrap|拔靴法]],那是「從機率到統計」那一篇會展開的:把你手上唯一的一份資料當成母體,從中重抽樣數千次,直接讀出某統計量的變異性。而當連「從目標中抽取獨立樣本」都不可能時——複雜的貝氏後驗的典型命運——下一篇就會引入馬可夫鏈蒙地卡羅,它建造一個聰明的隨機漫步,使其長期造訪頻率,恰好吻合你無法直接抽樣的那個分配。樸素的蒙地卡羅,是這一切所倚靠的地基。