Reservoir sampling is a family of randomized algorithms for randomly choosing a sample of k items from a list S containing 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.
Contents
Example: Sample size 1
Suppose we see a sequence of items, one at a time. We want to keep a single item in memory, and we want it to be selected at random from the sequence. If we know the total number of items (n), then the solution is easy: select an index i between 1 and n with equal probability, and keep the i-th element. The problem is that we do not always know n in advance. A possible solution is the following:
So:
Algorithm R
The most common example was labelled Algorithm R by Jeffrey Vitter in his paper on the subject. This simple O(n) algorithm as described in the Dictionary of Algorithms and Data Structures consists of the following steps (assuming k < s and using one-based array indexing):
The algorithm creates a "reservoir" array of size
To see this, consider the following proof by induction. After the
Reservoir with Random Sort
A simple reservoir-based algorithm can be designed using random sort and implemented using priority queue data structure. This algorithm assigns random number as keys to each item and maintain k items with minimum value for keys. In essence, this is equivalent to assigning a random number to each item as key, sorting items using these keys and taking top k items. The worse case run time of the algorithm is
Weighted Random Sampling using Reservoir
In many applications sampling is required to be according to the weights that are assigned to each items available in set. For example, it might be required to sample queries in a search engine with weight as number of times they were performed so that the sample can be analyzed for overall impact on user experience. There are two ways to interpret weights assigned to each item in the set:
- Let the weight of each item be
w i P i = w i / W . - Let the weight of two items i and j be
w i w j p i p j = p i max ( 1 , w j / w i ) .
Algorithm A-Res
The following algorithm was given by Efraimidis and Spirakis that uses interpretation 1:
This algorithm is identical to the algorithm given in Reservoir Sampling with Random Sort except for the line how we generate the key using random number generator. The algorithm is equivalent to assigning each item a key
Algorithm A-Chao
Following algorithm was given by M. T. Chao uses interpretation 2:
For each item, its relative weight is calculated and used to randomly decide if the item will be added into the reservoir. If the item is selected, then one of the existing items of the reservoir is uniformly selected and replaced with the new item. The trick here is that, if the probabilities of all items in the reservoir are already proportional to their weights, then by selecting uniformly which item to replace, the probabilities of all items remain proportional to their weight after the replacement.
Distributed Reservoir Sampling
In many applications, amount of data from which a small sample is needed is too large and it is desirable to distribute sampling tasks among many machines in parallel to speed up the process. A simple approach that is often used, although less performant, is to assign a random number as key to each item and then perform a distributed sort and finally obtain a sample of desired size from top k items. If weighted sample is desired then key is computed using
Another more efficient approach for distributed weighted random sampling is as follows:
- Distribute data among m machines.
- Each machine does its own weighted sampling using key
r 1 / w i - Collects all m samples of size <= k. We should have total items
n ′ <= m k . - Now sample k items from
n ′
The Step 4 uses keys from Step 2 because we might have unbalanced data distribution on machines. For example, lets say k = 1, machine m1 only gets 1 item with weight 10 while machine m2 gets 2 items each with weight 100. Intuitively probability for items from m1 getting in final sample is 10/210. In Step 3, we will get 1 item from m1 as well as m2. If we recalculate keys in step 4 then the probability that item from m1 will be in final sample is 10/110 instead of required 10/210. Now observe that weighted reservoir sampling algorithm from previous section decreases max key value in priority queue as it processes more items. Therefore, items sampled from machine with larger chunk will have lower key values and thus higher chance of getting selected.
Relation to Fisher-Yates shuffle
Suppose one wanted to draw k random cards from a deck of playing cards (i.e., n=52). A natural approach would be to shuffle the deck and then take the top k cards. In the general case, the shuffle also needs to work even if the number of cards in the deck is not known in advance, a condition which is satisfied by the inside-out version of the Fisher-Yates shuffle:
To initialize an array a of n elements to a randomly shuffled copy of S, both 0-based:a[0] ← S[0]
for i from 1 to n - 1 do
r ← random (0 .. i)
a[i] ← a[r]
a[r] ← S[i]
Note that although the rest of the cards are shuffled, only the top k are important in the present context. Therefore, the array a need only track the cards in the top k positions while performing the shuffle, reducing the amount of memory needed. Truncating a to length k, the algorithm is modified accordingly:
To initialize an array a to k random elements of S (which is of length n), both 0-based:a[0] ← S[0]
for i from 1 to k - 1 do
r ← random (0 .. i)
a[i] ← a[r]
a[r] ← S[i]
for i from k to n - 1 do
r ← random (0 .. i)
if (r < k) then a[r] ← S[i]
Since the order of the first k cards is immaterial, the first loop can be removed and a can be initialized to be the first k items of S. This yields Algorithm R.
Fast Approximation
A fast approximation to reservoir sampling. Uses a good-quality approximation to the sampling-gap distribution to skip over the gaps; i.e. consecutive runs of data that are not sampled.
Example implementation
The following is a simple implementation of the algorithm in Python that samples the set of English Wikipedia page titles:
Statistical properties
Probabilities of selection of the reservoir methods are discussed in Chao (1982) and Tillé (2006). While the first-order selection probabilities are equal to
Limitations
Reservoir sampling makes the assumption that the desired sample fits into main memory, often implying that