一道海量日誌的隨機選取問題

2021-06-05 04:45:18 字數 1397 閱讀 2069

原題是這樣的:

假設有100g的日誌存在於磁碟之上,其中每條日誌占用的空間不多於100個位元組,現在從日誌隨機選取n條日誌,保證每條日誌的選取概率相同。

解1:最簡單且嚴格的做法是掃瞄日誌兩遍。

第一遍:統計出日誌的總條數,m。

第二遍:掃瞄每條日誌以n/m的概率選擇該條日誌,直到滿足n條日誌。

解法2:

由於每條日誌的最大長度為100位元組,因此日誌數量至少有k = 1g條,因此可以在掃瞄日誌的時候進行隨機抽樣,使用乙個較大的概率比如 10 * n / k。 這樣選擇出的日誌條數肯定會大於n,並且總量遠小於100g。 接下來可以按第一種方法從樣本中隨機選擇出n條日誌。

ps: 解法1和2都比較簡單,但是會存在乙個非常嚴重的問題,都需要讀取所有的日誌,100g的資料在讀取時會非常耗時,最理想情況下以廠商的標準最快可以達到80m/s,這樣讀取100g的資料同樣需要1250s,即20多分鐘。那有沒有一種方法減少讀取磁碟的資料量?

解法3:假設檔案的總大小為s=100g,在邏輯上將文字分成b=100w塊,則每個塊的實際大小為k=s/b, 然後在邏輯上遍歷這100w個塊,給每個塊1/1000的選擇概率。這樣按偏移量從中選取1000個塊,在這1000個塊中隨機抽取n條日誌。這樣實際讀取的資料量大小為100m, 這已經非常小。

注:第三種方法可以會在每個日誌的選取概率上出現細微的區別,但是由於資料量巨大,故這種差別可以忽略。

定義取出的行號為choice,第一次直接以第一行作為取出行 choice ,而後第二次以二分之一概率決定是否用第二行替換 choice ,第三次以三分之一的概率決定是否以第三行替換 choice ……,以此類推,可用偽**描述如下: 

i = 0 

while more input lines 

with probability 1.0/++i 

choice = this input line 

print choice 

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

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

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

偽**: 

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 

一道海量日誌的隨機選取問題

原題是這樣的 假設有100g的日誌存在於磁碟之上,其中每條日誌占用的空間不多於100個位元組,現在從日誌隨機選取n條日誌,保證每條日誌的選取概率相同。解1 最簡單且嚴格的做法是掃瞄日誌兩遍。第一遍 統計出日誌的總條數,m。第二遍 掃瞄每條日誌以n m的概率選擇該條日誌,直到滿足n條日誌。解法2 由於...

海量資料等概率隨機選取問題

1 問題定義可以簡化如下 在不知道檔案總行數的情況下,如何從檔案中隨機的抽取一行?首先想到的是我們做過類似的題目嗎?當然,在知道檔案行數的情況下,我們可以很容易的用c執行庫的rand 函式隨機的獲得乙個行數,從而隨機的取出一行,但是,當前的情況是不知道行數,這樣如何求呢?我們需要乙個概念來幫助我們做...

一道概率問題

題目 有一輛汽車有n個座位,編號為1 n,有n個人買票拿號上車,正常人按照自己的座位號對號入座,但是有乙個精神病患者,在空座位中隨機選擇乙個空著的座位就坐,正常人的座位如果被佔,也將隨機選擇乙個空著就坐,假如第乙個上車的是精神病患者,其他人都是正常人,問最後乙個人能坐到自己的座位的概率是多少?對於概...