生活随笔
收集整理的這篇文章主要介紹了
蓄水池采样(Reservoir Sampling)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
在一個給定長度的數(shù)組中隨機等概率抽取一個數(shù)據(jù)很容易,但如果面對的是長度未知的海量數(shù)據(jù)流呢?蓄水池采樣(Reservoir Sampling)算法就是來解決這個問題的, 它在分析一些大數(shù)據(jù)集的時候非常有用。
?
細看后,我們可以對其進行擴展,假如從未知或者很大樣本空間隨機地取k個數(shù)?
類比下即可得到答案,即先把前k個數(shù)放入蓄水池,對第k+1,我們以k/(k+1)概率決定是否要把它換入蓄水池,換入時隨機的選取一個作為替換項,這樣一直做下去,對于任意的樣本空間n,對每個數(shù)的選取概率都為k/n。也就是說對每個數(shù)選取概率相等。
?
定理:該算法保證每個元素以 k / n 的概率被選入蓄水池數(shù)組。
證明:首先,對于任意的 i,第 i 個元素進入蓄水池的概率為 k / i;而在蓄水池內每個元素被替換的概率為 1 / k; 因此在第 i 輪第j個元素被替換的概率為 (k / i ) * (1 / k) = 1 / i。 接下來用數(shù)學歸納法來證明,當循環(huán)結束時每個元素進入蓄水池的概率為 k / n.
假設在 (i-1) 次迭代后,任意一個元素進入 蓄水池的概率為 k / (i-1)。有上面的結論,在第 i 次迭代時,該元素被替換的概率為 1 / i, 那么其不被替換的概率則為 1 - 1/i = (i-1)/i;在第i 此迭代后,該元素在蓄水池內的概率為 k / (i-1) * (i-1)/i = k / i. 歸納部分結束。
因此當循環(huán)結束時,每個元素進入蓄水池的概率為 k / n. 命題得證。
?
1 在一個給定長度的數(shù)組中隨機等概率抽取一個數(shù)據(jù)很容易,但如果面對的是長度未知的海量數(shù)據(jù)流呢?蓄水池采樣(Reservoir Sampling)算法就是來解決這個問題的, 它在分析一些大數(shù)據(jù)集的時候非常有用。
2 基本概念
3
4 細看后,我們可以對其進行擴展,假如從未知或者很大樣本空間隨機地取k個數(shù)?
5
6 類比下即可得到答案,即先把前k個數(shù)放入蓄水池,對第k+1,我們以k/(k+1)概率決定是否要把它換入蓄水池,換入時隨機的選取一個作為替換項,這樣一直做下去,對于任意的樣本空間n,對每個數(shù)的選取概率都為k/
n。也就是說對每個數(shù)選取概率相等。
7
8
9 算法的正確證明
10 定理:該算法保證每個元素以 k /
n 的概率被選入蓄水池數(shù)組。
11
12 證明:首先,對于任意的 i,第 i 個元素進入蓄水池的概率為 k / i;而在蓄水池內每個元素被替換的概率為 1 / k; 因此在第 i 輪第j個元素被替換的概率為 (k / i ) * (1 / k) = 1 / i。 接下來用數(shù)學歸納法來證明,當循環(huán)結束時每個元素進入蓄水池的概率為 k /
n.
13
14 假設在 (i-1) 次迭代后,任意一個元素進入 蓄水池的概率為 k / (i-1)。有上面的結論,在第 i 次迭代時,該元素被替換的概率為 1 / i, 那么其不被替換的概率則為 1 - 1/i = (i-1)/i;在第i 此迭代后,該元素在蓄水池內的概率為 k / (i-1) * (i-1)/i = k /
i. 歸納部分結束。
15
16 因此當循環(huán)結束時,每個元素進入蓄水池的概率為 k /
n. 命題得證。
17
18 Java實現(xiàn)
19 [java] view plain copy
20 import java.util.Arrays;
21 import java.util.Random;
22
23 public class ReservoirSamplingAlgorithm {
24 public static void main(String[] args) {
25 int k=10
;
26 int n=1000
;
27 int [] data=
new int [n];
28 for (
int i=0;i<n;i++
){
29 data[i]=
i;
30 }
31 int [] result=
reservoirSampling(data,k);
32 System.out.println(Arrays.toString(result));
33 }
34
35 public static int [] reservoirSampling(
int [] data,
int k){
36 if (data==
null ){
37 return new int [0
];
38 }
39 if (data.length<
k){
40 return new int [0
];
41 }
42 int [] result=
new int [k];
43 int n=
data.length;
44 for (
int i=0;i<n;i++
){
45 if (i<
k){
46 result[i]=data[i];<a href="http://www.cnblogs.com/HappyAngel/archive/2011/02/07/1949762.html" target="_blank">參考博客</a>
47 }
else {
48 int j=
new Random().nextInt(i);
49 if (j<
k){
50 result[j]=
data[i];
51 }
52 }
53 }
54 return result;
55 }
56 }
57
58
59
60 參考博客來源:參考博客
View Code ?
參考博客來源:參考博客
轉載于:https://www.cnblogs.com/kincolle/p/8266651.html
總結
以上是生活随笔 為你收集整理的蓄水池采样(Reservoir Sampling) 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內容還不錯,歡迎將生活随笔 推薦給好友。