標籤:蓄水池抽樣
問題:如何在無限大的資料流中隨機選取K個資料,保證當前遍曆過的i個元素中每一個元素被選中的機率均為 k/i?從而對於n個元素,每個元素被選中的機率均為 k/n。
解:對於前k個元素,我們直接選中放入一個虛擬蓄水池中,對於第 k+1 個元素,我們用 k/(k+1) 的機率選中它,一旦選中了,就隨機替換掉蓄水池中的某一個元素,這樣前 k 個被選中的元素在第 k+1 個元素到來時依然被選中的機率即為它不被替換掉的機率:
p = 1*(1-被替換掉的機率q)
q = k/(k+1) * 1/k #即前k個元素中某個元素被替換時,某個被替換的機率為 1/k
這樣 p = k/(k+1)
對於當前被遍曆到的第 k+1 個元素,它被放到蓄水池中的機率就是它被選中的機率,即 k/(k+1),因為只要它被選中,就一定會替換掉蓄水池中的某個元素而留在水池中;
同理,對於第 m +1 個元素(m>>k)的到來,前m個元素被選中的機率均為 k/m,進行第 m+1 次選擇時,前 m 個元素依然保留在蓄水池中的機率為:
p = k/m * { 1 - [ k/(m+1) * 1/k ] } = k/(m+1) #即 p=之前在水池中的機率*(1 - 被第m+1個元素替換替換掉的機率 )
或者 p = k/m * { (m+1-k)/(m+1) + [ k/(m+1) * (k-1)/k ] } = k/(m+1) #即 p=之前在水池中的機率*(第m+1個元素未被選中的機率 + 第m+1個元素被選中但是替換了其他k-1個元素的機率)
代碼實現時,遍曆到第 i 個元素時(i>k),可以直接產生一個 (1,i)之間的隨機數 r ,如果 r<=k,那麼就讓當前第 i 個元素替換蓄水池中的第 r 個元素即可,把選中和替換哪一個元素融合為一步了,機率是不變的,即被選中的機率為 k/i,蓄水池中的 k 個元素每一個被替換的機率也為 1/k 。
Init : a reservoir with the size: k for i= k+1 to N R=random(1, i); if( R < k) SWAP the R th value and i th value end for
參考:http://blog.csdn.net/lxmky/article/details/7951099
演算法學習之---蓄水池抽樣問題