前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >池塘抽样 Reservoir Sampling

池塘抽样 Reservoir Sampling

原创
作者头像
TimGallin
发布2022-01-30 16:29:03
6930
发布2022-01-30 16:29:03
举报
文章被收录于专栏:thinkythinky

什么是Reservoir Sampling

Reservoir Sampling,水塘抽样算法是随机算法的一种,通常用于选取简单随机样本。

Reservoir Sampling 的用途

对于一个固定样本,样本总数为n,要在其中随机抽取k个样本,我们可以通过在[0,n)中进行随机取数,以保证选取样本的随机性。但是,当n变成一个极大的不固定的数,大到无法将n个样本全部载入到内存中,那么上述通过[0,n)随机数的方式就不能达到期望。需要一种在n不确定情况下,也可以针对全部样本进行随机抽样的算法。Reservoir Sampling可以达到O(n)时间复杂度内与O(k)的空间复杂度。

实现

使用链表结构表示未知大小的样本总数,随机选取k个样本

代码语言:txt
复制
#1.将[0, k)个样本依次放入reservoir[k]中
#2.遍历I in [k, n),每次从[0, i]随机一个数r,假设r∈[0, k),则将reservoir[r]替换为m
class Solution:
    def __init__(self, head: Optional[ListNode]):
        self.head = head

    def getRandom(self, k: int) -> List:
        node, i = self.head, 0
        reservoir = [] 
        for _ in range(k) :
            reservoir.append(node)
            node = node.next
            i += 1
        while node:
            r = randrange(i) 
            if r < k:  
                reservoir[r] = node.val
            i += 1
            node = node.next
        return reservoir

证明

在未知样本streamn大小的前提下,这里对k个样本的随机性进行证明,也就是每个待选样本被选中的概率都是k/n。根据实现方式,可以将证明分为两部分

1. 证明范围在[k, n)的倒数k个数被选取的概率是k/n

对于这个范围内的每一个streami元素,执行的操作都是先从[0,i)随机一个数r,假设r<k,则将reservoirr替换为streami。考虑最后一个样本streamn-1被选中的概率,由于是最后一个样本,因此该样本一旦被选取,后续不会存在再被替换的可能。因此只要随机数小于k,则该样本被选中,即使概率是k/n。而对于倒数第二个样本,即streamn-2,它最终被选取的概率p应该是在遍历到n-2时该样本被选中的概率 乘以 最后一个样本所得到的随机数与上一个样本的随机数不同的概率。streamn-2被选中的概率是k/n-1,streamn-1被选中且不会替换掉streamn-1的概率,等同于streamn-1时的随机数与上一个随机数不同的概率,此时待选随机数有n个,由于上一个随机数是已经发生的事件,该随机数是一个固定的数字,那么在剩余n-1个数中任选一个数必然不会与上一个随机数相同,因此该概率是n-1/n。综上得出,streamn-2最终能被选中的概率p = (k/n-1) * (n-1/n) = k/n。

与以上推到过程类似,我们容易得出[k, n)范围内倒数k个样本,每个样本最终被选取的概率是k/n。

2. 证明[0, k)范围内前k个数,每个数最终被选取的概率是k/n

前个数初始化时就被按序放入reservoirk中,对于每个样本来说,最终被选取的概率,就是在[k, n)过程完成后还没有被替换的概率。以第一个样本为例,在第k+1个样本时不会替换第一个样本的概率,就是在[0, k+1)范围内取随机数不取到1的概率,也就是1 - (1/k+1) = k/k+1,以次类推,第一个样本最终被选取的概率p= k/(k+1) (k+1)/(k+2) ... * (n-1)/n = k/n。同理可得,在[0, k)范围内前k个数,每个数最终被选取的概率是k/n。

参阅

1.geekforgeeks, reservoir sampling

2.leetcode, 链表随机节点

3.wiki, reservoir sampling

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Reservoir Sampling
  • Reservoir Sampling 的用途
  • 实现
  • 证明
  • 参阅
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com