時間複雜度爲O(1)的抽樣算法——別名採樣(alias sample method)

本文首發於我的編程之路,文章地址:wangliguang.cn/?p=9
  當我們得到一個概率分佈,如何根據這個概率分佈抽樣是一個常見的問題。這篇文章將介紹alias method(別名採樣),這種算法的運行時間複雜度爲O(1)的,當然提前需要複雜度爲O(n)的預處理。下面我將通過一個例子介紹別名採樣算法。

問題背景

假設一共存在A,B,C,D四種情況,它們的概率分別爲 0.3,0.1,0.1,0.5。如何實現按概率抽樣呢?
  比較常用的一種方法是生成一個數組:1,2,2,3,3,3,4,4,4,4,其中1對應A,2對應B,以此類推。然後隨機在數組中抽取一個即可。這種方法簡單易實現,但是這是僅僅有4種情況時。當情況變多,這種方法就會佔用很大的空間了,所以並不適用於大規模的通用情況。
  另外,可以根據它們的概率密度分佈生成累積分佈:0.3,0.4,0.5,1。然後生成一個0-1之間的隨機數,看它落在哪個區間。然而,這時需要與臨界點進行比較。我們知道,插入有序數列最好的時間複雜度爲O(logn),所以這種方法複雜度較大。
  我們這篇文章提到的alias method可以實現以運行複雜度爲O(1)的方式抽樣。當然它需要預處理預處理的時間複雜度爲O(n),但是重複跑的時候,運行時間複雜度低纔是重要的。

別名採樣算法

下面介紹alias method的處理過程。
  我們知道等概率分佈抽樣的時間複雜度爲O(1),考慮一種情況,如果A,B,C,D概率分佈均爲0.25,那我們隨機生成1,2,3,4,抽中哪個就是哪個,複雜度自然爲O(1),這是等概率分佈抽樣的情況
  我們知道二項不等概率分佈抽樣的時間複雜度也爲O(1),如果只有兩個變量,比如A,B概率分佈爲 0.2,0.8.那我們用累積分佈的方法,小於0.2就是A, 大於就是B,只需比較一次,所以複雜度也是O(1),這是二項分佈抽樣的情況
  alias method就是把這兩種方法結合起來。
  仍然以本文一開始提出的例子爲例。原來的概率分佈如下,我們用綠色代表A,藍色代表B,紫色代表C,橙色代表D:
原始概率分佈
首先我們把原概率分佈乘以N(爲後面的拼接做準備),這裏是N=4。得到:1.2,0.4,0.4,2.0,如圖所示。
乘4後
  我們把它拼成等概率分佈和二項不等概率分佈:
處理後
  注意拼接的過程中,每一列最多有兩種情況,這樣才能讓每一列都符合二項分佈。
  做完以上處理後,我們就可以開始抽樣了。首先我們以等概率分佈抽一列,然後生成一個0-1之間的隨機數。
  舉例來說,例如我們首先抽中了第四列(概率爲0.25)。然後在第四列中進行二項分佈抽樣,如果小於0.8,綠色,代表A,反之,就是橙色,代表D。這兩個操作的複雜度均爲O(1),故總時間複雜度也爲O(1)。
  那麼這樣抽樣是正確的嗎?換句話說,在原概率分佈中抽到A的概率是0.3,那使用alias方法抽到的概率還是0.3嗎?
  我們仍然以抽取A情況爲例。原來抽中a的概率爲0.3。運用alias method方法後,抽中a的概率爲抽中第一列+抽中第四列且隨機數小於0.2,算起來爲0.25+ 0.25 * 0.2) = 0.3,完全一樣。

參考文獻

1, http://blog.csdn.net/sky_zhe/article/details/10051967
2, https://www.cnblogs.com/zqiguoshang/p/5885455.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章