mR 隨機抽樣

2021-07-08 15:17:24 字數 4768 閱讀 9103

1. 問題由來

google曾經有一道非常經典的面試題:

給你乙個長度為n的鍊錶。n很大,但你不知道n有多大。你的任務是從這n個元素中隨機取出k個元素。你只能遍歷這個鍊錶一次。你的演算法必須保證取出的元素恰好有k個,且它們是完全隨機的(出現概率均等)?

這道題的解法非常多,網上討論也非常熱烈。本文要討論的是,這個問題是從何而來,有什麼實用價值?

自從有了hadoop之後,該問題便有了新的應用載體。隨著資料量的增多,很多資料探勘演算法被轉移到mapreduce上實現,而資料探勘中有個基本的問題是怎樣對資料進行抽樣。在hadoop中,每個job會被分解成多個task平行計算,而資料的總量事先是不知道的(知道job執行結束才能獲取數總數,而資料量非常大時,掃瞄一遍資料的代價非常高),使用者知道的只是要獲取的樣本量,那怎樣在類似於hadoop的分布式平台上進行資料抽樣?

回過頭來看google的這道面試題,是不是正好時hadoop平台上海量資料抽樣問題?

2. 在hadoop上編寫抽樣程式

2.1 解法一

(1) 設計思想

蓄水池抽樣:先儲存前k個元素, 從第k+1個元素開始, 以1/i (i=k+1, k+2,…,n) 的概率選中第i個元素,並隨機替換掉乙個已儲存的記錄,這樣遍歷一次得到k個元素,可以保證完全隨機選取。

(2) mapreduce實現

使用者執行job時,需指定每個map task的取樣量。比如,使用者該job的map task個數為s,則每個map task需要採集k/s個元素。

(3) 優缺點分析

由於該job沒有reduce task,因而效率很高。

2.2 解法二

(1) 設計思想

依次掃瞄每個元素,為每個元素賦予乙個隨機的整數值;然後使用top k演算法(譬如最大k個整數)得到需要的k個元素。

(2) mapreduce實現

(3) 優缺點分析

該演算法比第一種演算法低效,但由於整個過程自然流暢,實現起來非常簡單,不易出錯。

2.3 解法三

(1) 設計思想

考慮第乙個元素,其以k/n的概率被選中;如果該節點被選中,則從剩下的(n-1)個元素中選出(k-1)個元素;如果沒有被選中,則從剩下的(n-1)個元素中選出k個元素,…,依次這樣下去,直到獲取k個元素。

(2) mapreduce實現

(3) 優缺點分析

由於該演算法沒有reduce task,效率比較高,但需要在inputformat中統計資料量,程式設計複雜度較高。

3. 延伸

這個問題與《程式設計珠璣》上討論的問題很相似:

輸入兩個整數m和n,其中m對於該問題,大致存在四種演算法,他們有不同的優缺點。

(1) 第一種方法來自knuth的《the art of computer programming, volume 2: seminumerical algorithms》

偽**是:

1

2

3

4

5

6

7

8

9

10

11

12

13

select = m

remaining = n

fori = [0 n )

if(bigrand() % remaining) < select

print i

select—

remaining—

只要m<=n,程式選出來的整數就恰為m個。

c++的實現如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

voidgenknuth(intm,intn)

}

}

該演算法非常節省空間,但需要全部掃瞄n個數,當n很多時,效率不高。

(2)第二種方法的複雜度只與m有關,採用了set(實際上是紅黑樹)節省時間。**如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

voidgensets(intm,intn)

// print s

}

該方法每次插入均在o(log m)時間內完成,但需要的空間開銷很大。

(3)第三種方法克服了(2)的缺點,**如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

voidgenshuf(intm,intn)

for(i = 0; i < m; i++)

sort(x, x+m);

//print result

}

該演算法需要n個元素的記憶體空間和o(n+mlogm)的時間,其效能通常不吐knuth的演算法。

(4)當m接近n時,基於集合的演算法生成的很多隨機數都要丟掉,因為之前的數已經存在於集合中了,為了改進這一點,演算法如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

voidgenfloyd(intm,intn)

else

}

//print results

}

4. 參考資料

(1) 《程式設計珠璣》第二版

(2)

MySQL隨機抽樣

最近由於需要大概研究了一下mysql的隨機抽取實現方法。舉個例子,要從tablename表中隨機提取一條記錄,大家一般的寫法就是 select from tablename order by rand limit 1。但是,後來我查了一下mysql的官方手冊,裡面針對rand 的提示大概意思就是,在...

R隨機抽樣

x為總體向量 n為樣本容量 replace f表示無放回抽樣 replace t表示放回抽樣 prob可以設定不等概率抽樣 sample x,n,replace f,prob null 用r模擬擲硬幣 h表示正面 t表示反面 有放回抽樣 sample c h t 10,replace t 1 h t...

hive 隨機抽樣

1.random sampling syntax select from distribute by rand sort by rand limit 2.bucket table sampling 該方式是最佳化取樣bucket表。rand 函式也可以用來取樣整行。如果取樣列同時使用了cluster...