蓄水池采样法

转载自https://blog.csdn.net/dm_ustc/article/details/45875971

在数据流处理中的一个常见问题就是数据采样问题。我们希望从流中选择一个子集,以便能够对它进行查询并给出统计性上对整个流具有代表性的结果。

蓄水池采样

具体问题是我们要从数据流中随机抽取k个元素。如果数据流长度m事先已经知道,那这个问题就非常简单,每个元素以k/m的概率选取即可。但这个问题要求m未知,那就不太好搞了。这个问题的解法是保存一个k大小的窗口。数据流的前k个元素依次加入到窗口。对于数据流第i个元素(i>k),以k/i的概率替换窗口中的某个元素。最终窗口的元素出现概率均为k/m。

下面使用数学归纳法给出该算法合理性的简单证明。

  1. 假设i=1,元素被选中的概率为1;

  2. 设前i个元素被选中的概率为k/i。对于第i+1个元素,我们以k/i+1的概率替换窗口中的元素。其中k/i为某个元素在第i+1个元素来到前被选中的概率。如果第i+1个元素替换窗口内的元素,则以1/k的概率从窗口选一个元素去除,将第i+1个元素添加进去。计算出的结果表明元素仍存在窗口的概率为k/(i+1)。得证。
    这里写图片描述

  3. 总结:对于第n个元素,如果n<=k,则放入代选窗口。否则,则以k/n的概率选中,并随机替换前面待选窗口内的随机一个元素。

一个实际例子(来自mining massive dataset)

1.问题:对于搜索引擎是不断有查询流的,这些数据可以用来研究典型用户的行为。假设数据流的每个元素由三元组组成(user,query,time)。假设想要查询“在过去一个月中典型用户所提交重复查询的比例是多少”。假设我们只希望存储1/10的元素。

2.错误做法

一个很容易的做法就是对于每个查询都以1/10的概率进行保存。但是这个方法对于我们的问题会带来错误结果。假定某用户在过去一个月有s个查询只提交过1次,有d个查询提交过两次,不存在提交超过2次的查询。该用户提交重复查询的比例为s/(s+d)。

如果我们的查询比例为1/10,那么在该用户的查询中,提交过1次的查询达到我们期望的s/10。而出现2次的d个查询中只有d/100会在样本中出现1次(两个相同的查询都出现在样本中的概率为(1/10)(1/10)=1/100),有18d/100的查询在样本中出现1次(两个相同的查询只有一个出现在样本中,概率为(1/10)(9/10)*2=(18/100))。则该用户提交重复查询比例为(d/100)/(d/100+s/10+18d/100)=d/(10s+19d)。显然和期望值不相等。

3.正确做法

对于这类问题,不能从每个用户查询的抽样样本中得到正确答案。所以我们必须挑选出1/10的用户,将他们的所有查询放入到样本中,而不考虑其他用户的查询。也就是说我们采样的对象不是查询,而是用户。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值