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

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

随机读取数据,如何保证真随机是不可能的,因为计算机的随机函数是伪随机的。

但是在不考虑计算机随机函数的情况下,如何保证数据的随机采样呢?

1.系统提供的shuffle函数

  C++/Java都提供有shuffle函数,可以对容器内部的数据打乱,保持随机排序。

  C++:

1 template <class RandomAccessIterator, class URNG>
2   void shuffle (RandomAccessIterator first, RandomAccessIterator last, URNG&& g);

  Java:

1 static void    shuffle(List<?> list);
2 static void    shuffle(List<?> list, Random rnd);

  这些函数对数量一定的数据的随机打乱顺序,并不能处理数量不定的数据流。

2.在序列流中取一个数,如何确保随机性,即取出某个数据的概率为:1/(已读取数据个数)

  假设已经读取n个数,现在保留的数是Ax,取到Ax的概率为(1/n)。

  对于第n+1个数An+1,以1/(n+1)的概率取An+1,否则仍然取Ax。依次类推,可以保证取到数据的随机性。

  数学归纳法证明如下:

    当n=1时,显然,取A1。取A1的概率为1/1。

           假设当n=k时,取到的数据Ax。取Ax的概率为1/k。

           当n=k+1时,以1/(k+1)的概率取An+1,否则仍然取Ax

    (1)如果取Ak+1,则概率为1/(k+1);

    (2)如果仍然取Ax,则概率为(1/k)*(k/(k+1))=1/(k+1)

  所以,对于之后的第n+1个数An+1,以1/(n+1)的概率取An+1,否则仍然取Ax。依次类推,可以保证取到数据的随机性。

  代码如下:

 1 //在序列流中取一个数,保证均匀,即取出数据的概率为:1/(已读取数据个数)
 2 void RandNum(){    
 3     int res=0;
 4     int num=0;
 5     num=1;
 6     cin>>res;
 7 
 8     int tmp;
 9     while(cin>>tmp){
10         if(rand()%(num+1)+1>num)
11             res=tmp;
12         num++;
13     }
14     cout<<"res="<<res<<endl;
15 }

3.在序列流中取k个数,如何确保随机性,即取出某个数据的概率为:k/(已读取数据个数)

  建立一个数组,将序列流里的前k个数,保存在数组中。(也就是所谓的"蓄水池")

  对于第n个数An,以k/n的概率取An并以1/k的概率随机替换“蓄水池”中的某个元素;否则“蓄水池”数组不变。依次类推,可以保证取到数据的随机性。

  数学归纳法证明如下:

    当n=k是,显然“蓄水池”中任何一个数都满足,保留这个数的概率为k/k。

           假设当n=m(m>k)时,“蓄水池”中任何一个数都满足,保留这个数的概率为k/m。

           当n=m+1时,以k/(m+1)的概率取An,并以1/k的概率,随机替换“蓄水池”中的某个元素,否则“蓄水池”数组不变。则数组中保留下来的数的概率为:

 

  所以,对于第n个数An,以k/n的概率取An并以1/k的概率随机替换“蓄水池”中的某个元素;否则“蓄水池”数组不变。依次类推,可以保证取到数据的随机性。

  代码如下:

 1 //在序列流中取n个数,保证均匀,即取出数据的概率为:n/(已读取数据个数)
 2 void RandKNum(int n){
 3     int *myarray=new int[n];
 4     for(int i=0;i<n;i++)
 5         cin>>myarray[i];
 6 
 7     int tmp=0;
 8     int num=n;
 9     while(cin>>tmp){
10         if(rand()%(num+1)+1<n)    
11             myarray[rand()%n]=tmp;
12     }
13 
14     for(int i=0;i<n;i++)
15         cout<<myarray[i]<<endl;
16 }

 

相关文章
|
7月前
|
算法 数据可视化
R语言马尔可夫MCMC中的METROPOLIS HASTINGS,MH算法抽样(采样)法可视化实例
R语言马尔可夫MCMC中的METROPOLIS HASTINGS,MH算法抽样(采样)法可视化实例
R语言马尔可夫MCMC中的METROPOLIS HASTINGS,MH算法抽样(采样)法可视化实例
|
7月前
|
算法 数据可视化 Python
Python用MCMC马尔科夫链蒙特卡洛、拒绝抽样和Metropolis-Hastings采样算法
Python用MCMC马尔科夫链蒙特卡洛、拒绝抽样和Metropolis-Hastings采样算法
|
7月前
|
机器学习/深度学习 算法
R语言使用Metropolis- Hasting抽样算法进行逻辑回归
R语言使用Metropolis- Hasting抽样算法进行逻辑回归
|
机器学习/深度学习 传感器 算法
基于类帕累托贯序抽样算法求解单目标优化问题附matlab代码
基于类帕累托贯序抽样算法求解单目标优化问题附matlab代码
|
人工智能 算法 Java
我整理了50道经典Java算法题,直接进了字节跳动!!
最近,很多小伙伴都想进入字节跳动这个快速发展的公司,而字节跳动对于算法的要求比较高。于是乎,有些小伙伴问我能否整理一些基础的算法题,帮助他们提升下基础算法能力。我:没问题啊!于是,经过半个多月的收集和整理,最终输出了这50道经典的Java算法题。
3395 0
|
存储 算法
一文足矣——动态规划经典之Floyd(弗洛伊德)算法
一文足矣——动态规划经典之Floyd(弗洛伊德)算法
253 0
一文足矣——动态规划经典之Floyd(弗洛伊德)算法
|
算法
一个古老而又经典的算法-汉诺塔问题
哈诺塔问题相信只要学习计算机的人都知道。这是一个古老而又伟大的问题。在这篇文章中,主要是给出递归解决汉诺塔问题的代码方法。毕竟面试的时候,HR比我们要变态很多,怎么蹂躏我们怎么玩。
257 0
一个古老而又经典的算法-汉诺塔问题
|
缓存 运维 负载均衡
真是经典中的经典!MySQL+多线程+Redis+算法+网络
真是经典中的经典!MySQL+多线程+Redis+算法+网络
真是经典中的经典!MySQL+多线程+Redis+算法+网络
|
存储 数据采集 人工智能
搜索引擎背后的经典数据结构和算法
搜索引擎背后的经典数据结构和算法