前言:
蓄水池抽樣:從N個元素中隨機的等概率的抽取k個元素,其中N無法確定。
適用場景:
模式識別等概率抽樣,抽樣查看漸增的log日志(無法先保存整個數據流然后再從中選取,而是期望有一種將數據流遍歷一遍就得到所選取的元素,並且保證得到的元素是隨機的算法)。
偽代碼:
init : a reservoir with the size: k for i= k+1 to N M=random(1, i); if( M < k) SWAP the Mth value and ith value end for
解釋:先選中第1到k個元素,作為被選中的元素。然后依次對第k+1至第N個元素做如下操作:每個元素都有k/x的概率被選中,然后等概率的(1/k)替換掉被選中的元素。其中x是元素的序號
原理:
蓄水池抽樣算法:
- 先選取
個元素中的前
個元素,保存在集合
中;
- 從第
個元素開始,每次先以概率
選擇是否讓第
個元素留下。若第
個元素存活,則從
中隨機選擇一個元素並用該元素
替換它;否則直接淘汰該元素
;
- 重復1和2,直到結束。最后集合
中剩下的就是保證隨機抽取的
個元素。
蓄水池抽樣算法正確性證明:
為了證明該算法的正確性,我們要保證算法結束后,原個元素每一個最后存活下來的概率都是
(因為從
個元素中隨機抽取
個元素,每個元素被抽中的概率都是
)。形式化地,我們要證明的結論是:在算法的第i(0<=i<=n-k)輪,前k+i個元素每一個存活下來的概率是k/k+i 。
數學歸納證明:
當時,結論顯然成立。
當時,根據算法,元素
存活的概率為
。而對於元素
,有兩種情況會使其存活下來:要么元素
直接被淘汰;要么元素
留下,但是沒有替換掉元素
。由歸納假設,
時結論成立,故元素
存活的概率為
,得證
舉例描述輔助數學證明:
每次都是以 k/i 的概率來選擇,例: k=1000的話, 從1001開始作選擇,1001被選中的概率是1000/1001,1002被選中的概率是1000/1002,與直覺是相符的。
假設當前是i+1, 按照我們的規定,i+1這個元素被選中的概率是k/i+1,也即第 i+1 這個元素在蓄水池中出現的概率是k/i+1,
此時考慮前i個元素,如果前i個元素出現在蓄水池中的概率都是k/i+1的話,說明我們的算法是沒有問題的。
對這個問題可以用歸納法來證明:
1. k < i <=N 1.當i=k+1的時候,蓄水池的容量為k,第k+1個元素被選擇的概率明顯為k/(k+1), 此時前k個元素出現在蓄水池的概率為 k/(k+1), 很明顯結論成立。
2.假設當 j=i 的時候結論成立,此時以 k/i 的概率來選擇第i個元素,前i-1個元素出現在蓄水池的概率都為k/i。
3.證明當j=i+1的情況: 即需要證明當以 k/i+1 的概率來選擇第i+1個元素的時候,此時任一前i個元素出現在蓄水池的概率都為k/(i+1). 前i個元素出現在蓄水池的概率有2
部分組成, ①在第i+1次選擇前得出現在蓄水池中,②得保證第i+1次選擇的時候不被替換掉 ①.由2知道在第i+1次選擇前,任一前i個元素出現在蓄水池的概率都為k/i ②.考慮
被替換的概率: 首先要被替換得第 i+1 個元素被選中(不然不用替換了)概率為 k/i+1,其次是因為隨機替換的池子中k個元素中任意一個,所以不幸被替換的概率是 1/k,故
前i個元素(池中元素)中任一被替換的概率 = k/(i+1) * 1/k = 1/i+1 則(池中元素中)沒有被替換的概率為: 1 - 1/(i+1) = i/i+1 綜合① ②,通過乘法規則 得到前i個元素出現在蓄水池
的概率為 k/i * i/(i+1) = k/i+1 故證明成立!!!
實現代碼和偽代碼類似,就不贅述了