引言
在统计学习里面,采样通常分为两类,unbiased Sample(无偏采样)和biased Sample(有偏采样)。本文介绍的蓄水次采样就是一种无偏采样算法。它的特点是在对不知道样本总体个数或者样本总体个数太大,大到无法全部存放在内存中的情况下,可以保证每个样本被选取的概率是一样的,为K/N,其中K为“蓄水池”的大小,N为当前数据流中包含的样本个数。
算法描述
假设有一个数据流,其中包含的样本个数未知。现在有一个长度为K的缓存,现在需要从这个数据流中采样K个样本,满足:数据流中每个样本被选中的概率一样。算法过程如下:
- 数据流前K个样本直接依次放入到缓存中。n:表示当前处理过的样本个数
- 当n>k时,每个样本以k/n的概率被选中,一旦该样本被选中,则需要从原本被选中的K个样本随机选择一个样本丢弃,腾出空间存放新的被选中的样本。n++。
- 如此重复过程2即可。
算法的伪码如下:
void reserviorSample(...){
data:current data from data stream
i:Int
n:the number of data
s[1:K]:array which is used to store sampled data
data=get(datastream);
if(n<=K){
s[n]=data;
}else{
i=rand(n);
if(i<k){
s[i]=data;
}
}
n++;
}
结论:当前处理了n个流数据点后,任何数据点被保存在蓄水池中的概率是一样的,都是K/n。
算法证明
证明的方法有很多,可以使用归纳法对保存在蓄水池中的某一个样本做归纳推理即可。
现使用直接推理法:
当n<=K时,证明tirval。
当n>K时,对于当前的数据点data,我们考虑它被采样选中的概率。根据算法的描述,可知,当前状态下data被选中的概率:
P(data is s