Reservoir Sampling - 蓄水池抽样算法

        问题:如何随机从n个对象中选择一个对象,这n个对象是按序排列的,但是在此之前你是不知道n的值的。

 思路:如果我们知道n的值,那么问题就可以简单的用一个大随机数rand()%n得到一个确切的随机位置,那么该位置的对象就是所求的对象,选中的概率是1/n。

但现在我们并不知道n的值,这个问题便抽象为蓄水池抽样问题,即从一个包含n个对象的列表S中随机选取k个对象,n为一个非常大或者不知道的值。通常情况下,n是一个非常大的值,大到无法一次性把所有列表S中的对象都放到内存中。我们这个问题是蓄水池抽样问题的一个特例,即k=1。

解法:我们总是选择第一个对象,以1/2的概率选择第二个,以1/3的概率选择第三个,以此类推,以1/m的概率选择第m个对象。当该过程结束时,每一个对象具有相同的选中概率,即1/n,证明如下。

证明:第m个对象最终被选中的概率P=选择m的概率*其后面所有对象不被选择的概率,即

对应蓄水池抽样问题,可以类似的思路解决。先把读到的前k个对象放入“水库”,对于第k+1个对象开始,以k/(k+1)的概率选择该对象,以k/(k+2)的概率选择第k+2个对象,以此类推,以k/m的概率选择第m个对象(m>k)。如果m被选中,则随机替换水库中的一个对象。最终每个对象被选中的概率均为k/n,证明如下。

证明:第m个对象被选中的概率=选择m的概率*(其后元素不被选择的概率+其后元素被选择的概率*不替换第m个对象的概率),即

原文地址:https://www.cnblogs.com/ranjiewen/p/8973332.html

时间: 2024-10-13 12:59:18

Reservoir Sampling - 蓄水池抽样算法的相关文章

Reservoir Sampling 蓄水池抽样算法,经典抽样

随机读取数据,如何保证真随机是不可能的,因为计算机的随机函数是伪随机的. 但是在不考虑计算机随机函数的情况下,如何保证数据的随机采样呢? 1.系统提供的shuffle函数 C++/Java都提供有shuffle函数,可以对容器内部的数据打乱,保持随机排序. C++: 1 template <class RandomAccessIterator, class URNG> 2 void shuffle (RandomAccessIterator first, RandomAccessIterato

Reservoir Sampling - 蓄水池抽样

问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the objects sequentially but you do not know the value of n beforehand? For concreteness, how would you read a text file, and select and print one random l

蓄水池抽样算法

问题定义: 给你一个长度为N的链表.N很大,但你不知道N有多大.你的任务是从这N个元素中随机取出k个元素.你只能遍历这个链表一次.你的算法必须保证取出的元素恰好有k个,且它们是完全随机的(出现概率均等). 蓄水池抽样算法: 该算法是针对从一个序列中随机抽取不重复的k个数,保证每个数被抽取到的概率为k/n这个问题而构建的.做法是: - 首先构建一个可放k个元素的蓄水池,将序列的前k个元素放入蓄水池中. 然后从第k+1个元素开始,以k/n的概率来决定该元素是否被替换到池子中. 当遍历完所有元素之后,

MySTL:蓄水池抽样算法

给你一个长度为N的链表.N很大,但你不知道N有多大.你的任务是从这N个元素中随机取出k个元素.你只能遍历这个链表一次.你的算法必须保证取出的元素恰好有k个,且它们是完全随机的(出现概率均等). 这一题应该可以用来解决微信红包分配之类的那种问题,主要是概率的证明挺有意思. 1 #include <iostream> 2 #include <algorithm> 3 #include <time.h> 4 5 using namespace std; 6 7 typedef

海量数据处理之蓄水池抽样算法

一.问题由来 这个题目的由来是在<编程珠玑>里遇到的,故记录一下.还可以这么说,”如何从二进制文件中等概率取整数?”或者”在不知道文件总行数的情况下,如何从文件中随机的抽取一行?”这个题目说的有点不清楚实际上是:一个二进制文件中有好多好多整数,你要随机取出一个. 这个问题的难点就在于你开始不知道有多少的整数,也就是说这个(1/n)你不知道n是多少. 综上,随机抽样问题表示如下:要求从N个元素中随机的抽取k个元素,其中N无法确定. 这种应用的场景一般是数据流的情况下,由于数据只能被读取一次,而且

转-spark抽样之蓄水池抽样

1.蓄水池抽样算法(Reservoir Sampling) https://www.jianshu.com/p/7a9ea6ece2af 2.spark抽样之蓄水池抽样 https://blog.csdn.net/snaillup/article/details/69524931?utm_source=blogxgwz3 代码: /** * Reservoir sampling implementation that also returns the input size. * * @param

Spark MLlib之水塘抽样算法(Reservoir Sampling)

1.理解 问题定义可以简化如下:在不知道文件总行数的情况下,如何从文件中随机的抽取一行? 首先想到的是我们做过类似的题目吗?当然,在知道文件行数的情况下,我们可以很容易的用C运行库的rand函数随机的获得一个行数,从而随机的取出一行,但是,当前的情况是不知道行数,这样如何求呢?我们需要一个概念来帮助我们做出猜想,来使得对每一行取出的概率相等,也即随机.这个概念即蓄水池抽样(Reservoir Sampling). 水塘抽样算法(Reservoir Sampling)思想: 在序列流中取一个数,如

洗牌算法与蓄水池抽样

今儿看到了,就在此记录一下吧. 洗牌算法 递归做法:先将1~n-1洗牌,然后取随机数k(0<k<n),并交换n与k,代码很简单: 1 int[] shuffle(int[] cards, int n){ 2 if(n == 1){ 3 return cards; 4 } 5 shuffle(cards, n-1); 6 int k = random(1, n-1); 7 swap(card[k], card[n]); 8 return card; 9 } 也可以转成非递归的: 1 void s

蓄水池抽样Reservior Sampling

编程珠玑第12章练习题10: 如何从n个对象(可以依次看到这n个对象,但事先不知道n的值)中随机选择一个?具体说来,如何在事先不知道文本文件行数的情况下读取文件,从中随机选择并输出一行? 解答:我们总选择 第1行,并以概率1/2选择第2行,以概率1/3选择第3行,依次类推,在这一过程结束时,每一行选中的概率是相等的(都是1/n,其中n是文件的总行数) i = 0; while more input lines with probability 1.0/++i choice = this inpu