因爲需要用到Alias Sampling Method的方法,但是查了一下,發現沒有找到靠譜的關於Alias Method的中文介紹,所以乾脆自己寫一個好了。
關於Alias Method的介紹的比較好的是一個外國Blog:Darts, Dice, and Coins: Sampling from a Discrete Distribution,以下的介紹也主要參考這篇Blog裏的算法。
問題:比如一個隨機事件包含四種情況,每種情況發生的概率分別爲:
最容易想到的方法
我之前有在【數學】均勻分佈生成其他分佈的方法中寫過均勻分佈生成其他分佈的方法,這種方法就是產生0~1之間的一個隨機數,然後看起對應到這個分佈的CDF中的哪一個,就是產生的一個採樣。比如落在0~
但是這樣的複雜度,如果用BST樹來構造上面這個的話,時間複雜度爲
一個Naive的辦法
一個Naive的想法如下:
1. 可以像上圖這樣採樣,將四個事件排成4列:1~4,扔兩次骰子,第一次扔1~4之間的整數,決定落在哪一列。
2. 如上如所示,將其按照最大的那個概率進行歸一化。在1步中決定好哪一列了之後,扔第二次骰子,0~1之間的任意數,如果落在了第一列上,不論第二次扔幾,都採樣時間A,如果落在第二列上,第二次扔超過
3. 這樣算法複雜度最好爲
那怎麼去改進呢?
Alias Method
這樣Alias Method採樣方法就橫空出世了
還是如上面的那樣的思路,但是如果我們不按照其中最大的值去歸一化,而是按照其均值歸一化。即按照
其總面積爲N,然後可以將其分成一個1*N的長方形,如下圖:
將前兩個多出來的部分補到後面兩個缺失的部分中。
先將1中的部分補充到4中:
這時如果,將1,2中多出來的部分,補充到3中,就麻煩了,因爲又陷入到如果從中採樣超過2個以上的事件這個問題中,所以Alias Method一定要保證:每列中最多隻放兩個事件
所以此時需要講1中的補滿3中去:
再將2中的補到1中:
至此整個方法大功告成
Alias Method具體算法如下:
1. 按照上面說的方法,將整個概率分佈拉平成爲一個1*N的長方形即爲Alias Table,構建上面那張圖之後,儲存兩個數組,一個裏面存着第
2.產生兩個隨機數,第一個產生1~N 之間的整數i,決定落在哪一列。扔第二次骰子,0~1之間的任意數,判斷其與Prab[i]大小,如果小於Prab[i],則採樣i,如果大於Prab[i],則採樣Alias[i]
這個算法是不是非常的精妙而且簡潔,做到了
Alias Method程序化構建
Naive方法
構建方法:
1.找出其中面積小於等於1的列,如i列,這些列說明其一定要被別的事件矩形填上,所以在Prab[i]中填上其面積
2.然後從面積大於1的列中,選出一個,比如j列,用它將第i列填滿,然後Alias[i] = j,第j列面積減去填充用掉的面積。
以上兩個步驟一直循環,直到所有列的面積都爲1了爲止。
存在性證明
那麼Alias Table一定存在嗎,如何去證明呢?
要證明Alias Table一定存在,就說明上述的算法是能夠一直運行下去,直到所有列的面積都爲1了爲止,而不是會中間卡住。
一個直覺就是,這一定是可以一直運行下去的。上述方法每運行一輪,就會使得剩下的沒有匹配的總面積減去1,在第n輪,剩下的面積爲N-n,如果存在有小於1的面積,則一定存在大於1的面積,則一定可以用大於1的面積那部分把小於1部分給填充到1,這樣就進入到了第n+1輪,最後一直到所有列面積都爲1。
更爲嚴謹的證明見上面給出的那個Blog。
更快的構建方法
如果按照上面的方法去構建Alias Table,算法複雜度是
這樣算法複雜度爲
至此Alias Method就講完了,感覺還是一個非常精妙的方法,而且方法實現起來也非常的簡單。值得學習。