蓄水池抽样(Reservoir Sampling)

        蓄水池抽样解决的问题是当不知道N的大小时从N个数中等概率抽取k个数。

        要理解这个问题,首先从抽取一个数来看。

    在知道数字总数N的大小的情况下,我们可以很容易的用C运行库的rand函数随机的获得一个数字编号,从而随机的取出一个数字,但是,当前的情况是不知道N的大小,这种情况下我们需要这么做:定义取出的数字编号为choice,第一次直接以第一个数字作为取出数字 choice ,而后第二次以二分之一概率决定是否用第二个数字替换 choice ,第三次以三分之一的概率决定是否以第三个数字替换 choice ……,以此类推,可用伪代码描述如下:

  
  
  
  
  1.  i= 0  
  2.  
  3. while more input numbers  
  4.            with probability 1.0/++i  
  5.  
  6.                    choice = this input number  
  7. print choice  

    这种方法的巧妙之处在于成功的构造出了一种方式使得最后可以证明对每一个数字的取出概率都为1/n(其中n为当前输入的数字总数),换句话说对每一个数字取出的概率均相等,也即完成了随机的选取。

  证明如下:

    回顾这个问题,我们可以对其进行扩展,即如何从未知或者很大样本空间随机地取k个数?

  类比下即可得到答案,即先把前k个数放入蓄水池,对第k+1,我们以k/(k+1)概率决定是否要把它换入蓄水池,换入时随机的选取一个作为替换项,这样一直做下去,对于任意的样本空间n,对每个数的选取概率都为k/n。也就是说对每个数选取概率相等。

  伪代码:

  
  
  
  
  1. Init : a reservoir with the size: k  
  2.  
  3. for ik+1 to N  
  4.  
  5.     M=random(1, i);  
  6.  
  7.     if( M < k)  
  8.  
  9.      SWAP the Mth value and ith value  
  10.  
  11. end for   

        证明如下:

摘自http://www.cnblogs.com/HappyAngel/archive/2011/02/07/1949762.html

你可能感兴趣的:(职场,休闲,choice,蓄水池)