海量數據等概率隨機抽樣-蓄水池算法


問題起源於編程珠璣Column 12中的題目10,其描述如下:

How could you select one of n objects at random, where you see the objects sequentially but you do not know the value of n beforehand? For concreteness, how would you read a text file, and select and print one random line, when you don’t know the number of lines in advance?

問題定義可以簡化如下:在不知道文件總行數的情況下,如何從文件中隨機的抽取一行?

首先想到的是我們做過類似的題目嗎?當然,在知道文件行數的情況下,我們可以很容易的用C運行庫的rand函數隨機的獲得一個行數,從而隨機的取出一行,但是,當前的情況是不知道行數,這樣如何求呢?我們需要一個概念來幫助我們做出猜想,來使得對每一行取出的概率相等,也即隨機。這個概念即蓄水池抽樣(Reservoir Sampling)

有了這個概念,我們便有了這樣一個解決方案:定義取出的行號為choice,第一次直接以第一行作為取出行 choice ,而后第二次以二分之一概率決定是否用第二行替換 choice ,第三次以三分之一的概率決定是否以第三行替換 choice ……,以此類推。

這種方法的巧妙之處在於成功的構造出了一種方式使得最后可以證明對每一行的取出概率都為1/n(其中n為當前掃描到的文件行數),換句話說對每一行取出的概率均相等,也即完成了隨機的選取。

回顧這個問題,我們可以對其進行擴展,即如何從未知或者很大樣本空間隨機地取k個數?

類比下即可得到答案,即先把前k個數放入蓄水池,對第k+1,我們以k/(k+1)概率決定是否要把它換入蓄水池,換入時隨機的選取一個作為替換項,這樣一直做下去,對於任意的樣本空間n,對每個數的選取概率都為k/n。也就是說對每個數選取概率相等。

以上摘自 參考[1]。

 

參考

[1] Reservoir Sampling - 蓄水池抽樣 http://www.cnblogs.com/HappyAngel/archive/2011/02/07/1949762.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM