Reservoir Sampling

来源:互联网 发布:剑灵男灵族捏脸数据图 编辑:程序博客网 时间:2024/05/17 07:06

Reservoir sampling is a family of randomized algorithms for randomly choosing k samples from a list of n items, where n is either a very large or unknown number. Typically n is large enough that the list doesn’t fit into main memory.

Solution:

1) Create an array reservoir[0..k-1] and copy first k items of stream[] to it.
2) Now one by one consider all items from (k+1)th item to nth item.
a) Generate a random number from 0 to i where i is index of current item in stream[]. Let the generated random number is j.
b) If j is in range 0 to k-1, replace reservoir[j] with arr[i].

Code:

array R[k];    // resultinteger i, j;// fill the reservoir arrayfor each i in 1 to k do    R[i] := S[i]done;// replace elements with gradually decreasing probabilityfor each i in k+1 to length(S) do    j := random(1, i);   // important: inclusive range    if j <= k then        R[j] := S[i]    fidone

How does this work?
To prove that this solution works perfectly, we must prove that the probability that any item stream[i]where 0 <= i < n will be in final reservoir[] is k/n. Let us divide the proof in two cases as first k items are treated differently.

Case 1: For last n-k stream items, i.e., for stream[i] where k <= i < n 
For every such stream item stream[i], we pick a random index from 0 to i and if the picked index is one of the first k indexes, we replace the element at picked index with stream[i]

To simplify the proof, let us first consider the last item. The probability that the last item is in final reservoir = The probability that one of the first k indexes is picked for last item = k/n (the probability of picking one of the k items from a list of size n)

Let us now consider the second last item. The probability that the second last item is in final reservoir[]= [Probability that one of the first k indexes is picked in iteration for stream[n-2]] X [Probability that the index picked in iteration for stream[n-1] is not same as index picked for stream[n-2] ] = [k/(n-1)]*[(n-1)/n] = k/n.

Similarly, we can consider other items for all stream items from stream[n-1] to stream[k] and generalize the proof.

Case 2: For first k stream items, i.e., for stream[i] where 0 <= i < k 
The first k items are initially copied to reservoir[] and may be removed later in iterations for stream[k]to stream[n].
The probability that an item from stream[0..k-1] is in final array = Probability that the item is not picked when items stream[k], stream[k+1], …. stream[n-1] are considered = [k/(k+1)] x [(k+1)/(k+2)] x [(k+2)/(k+3)] x … x [(n-1)/n] = k/n

From: http://www.geeksforgeeks.org/reservoir-sampling/

From: http://en.wikipedia.org/wiki/Reservoir_sampling


原创粉丝点击