前言:

  蓄水池抽样:从N个元素中随机的等概率的抽取k个元素,其中N无法确定。

适用场景:

  模式识别等概率抽样,抽样查看渐增的log日志(无法先保存整个数据流然后再从中选取,而是期望有一种将数据流遍历一遍就得到所选取的元素,并且保证得到的元素是随机的算法)。

伪代码:

init : a reservoir with the size: k
for i= k+1 to N
M=random(1, i);
if( M < k)
SWAP the Mth value and ith value
end for

  解释:先选中第1到k个元素,作为被选中的元素。然后依次对第k+1至第N个元素做如下操作:每个元素都有k/x的概率被选中,然后等概率的(1/k)替换掉被选中的元素。其中x是元素的序号

原理:

  蓄水池抽样算法:

  1. 先选取蓄水池抽样(原理&amp;实现)-LMLPHP个元素中的前蓄水池抽样(原理&amp;实现)-LMLPHP个元素,保存在集合蓄水池抽样(原理&amp;实现)-LMLPHP中;
  2. 从第蓄水池抽样(原理&amp;实现)-LMLPHP个元素开始,每次先以概率蓄水池抽样(原理&amp;实现)-LMLPHP选择是否让第蓄水池抽样(原理&amp;实现)-LMLPHP个元素留下。若第蓄水池抽样(原理&amp;实现)-LMLPHP个元素存活,则从蓄水池抽样(原理&amp;实现)-LMLPHP中随机选择一个元素并用该元素蓄水池抽样(原理&amp;实现)-LMLPHP替换它;否则直接淘汰该元素蓄水池抽样(原理&amp;实现)-LMLPHP
  3. 重复1和2,直到结束。最后集合蓄水池抽样(原理&amp;实现)-LMLPHP中剩下的就是保证随机抽取的蓄水池抽样(原理&amp;实现)-LMLPHP个元素。

  蓄水池抽样算法正确性证明:
    为了证明该算法的正确性,我们要保证算法结束后,原蓄水池抽样(原理&amp;实现)-LMLPHP个元素每一个最后存活下来的概率都是蓄水池抽样(原理&amp;实现)-LMLPHP(因为从蓄水池抽样(原理&amp;实现)-LMLPHP个元素中随机抽取蓄水池抽样(原理&amp;实现)-LMLPHP个元素,每个元素被抽中的概率都是蓄水池抽样(原理&amp;实现)-LMLPHP)。形式化地,我们要证明的结论是:在算法的第i(0<=i<=n-k)轮,前k+i个元素每一个存活下来的概率是k/k+i 。

数学归纳证明:

蓄水池抽样(原理&amp;实现)-LMLPHP时,结论显然成立。

蓄水池抽样(原理&amp;实现)-LMLPHP时,根据算法,元素蓄水池抽样(原理&amp;实现)-LMLPHP存活的概率为蓄水池抽样(原理&amp;实现)-LMLPHP。而对于元素蓄水池抽样(原理&amp;实现)-LMLPHP,有两种情况会使其存活下来:要么元素蓄水池抽样(原理&amp;实现)-LMLPHP直接被淘汰;要么元素蓄水池抽样(原理&amp;实现)-LMLPHP留下,但是没有替换掉元素蓄水池抽样(原理&amp;实现)-LMLPHP。由归纳假设,蓄水池抽样(原理&amp;实现)-LMLPHP时结论成立,故元素蓄水池抽样(原理&amp;实现)-LMLPHP存活的概率为蓄水池抽样(原理&amp;实现)-LMLPHP,得证

  举例描述辅助数学证明:

每次都是以 k/i 的概率来选择,例: k=1000的话, 从1001开始作选择,1001被选中的概率是1000/1001,1002被选中的概率是1000/1002,与直觉是相符的。

假设当前是i+1, 按照我们的规定,i+1这个元素被选中的概率是k/i+1,也即第 i+1 这个元素在蓄水池中出现的概率是k/i+1,

此时考虑前i个元素,如果前i个元素出现在蓄水池中的概率都是k/i+1的话,说明我们的算法是没有问题的。

对这个问题可以用归纳法来证明:

  1. k < i <=N 1.当i=k+1的时候,蓄水池的容量为k,第k+1个元素被选择的概率明显为k/(k+1), 此时前k个元素出现在蓄水池的概率为 k/(k+1), 很明显结论成立。

2.假设当 j=i 的时候结论成立,此时以 k/i 的概率来选择第i个元素,前i-1个元素出现在蓄水池的概率都为k/i。

3.证明当j=i+1的情况: 即需要证明当以 k/i+1 的概率来选择第i+1个元素的时候,此时任一前i个元素出现在蓄水池的概率都为k/(i+1). 前i个元素出现在蓄水池的概率有2

部分组成, ①在第i+1次选择前得出现在蓄水池中,②得保证第i+1次选择的时候不被替换掉 ①.由2知道在第i+1次选择前,任一前i个元素出现在蓄水池的概率都为k/i ②.考虑

被替换的概率: 首先要被替换得第 i+1 个元素被选中(不然不用替换了)概率为 k/i+1,其次是因为随机替换的池子中k个元素中任意一个,所以不幸被替换的概率是 1/k,故

前i个元素(池中元素)中任一被替换的概率 = k/(i+1) * 1/k = 1/i+1 则(池中元素中)没有被替换的概率为: 1 - 1/(i+1) = i/i+1 综合① ②,通过乘法规则 得到前i个元素出现在蓄水池

的概率为 k/i * i/(i+1) = k/i+1 故证明成立!!!

实现代码和伪代码类似,就不赘述了

05-03 23:26