水库抽样算法
整理自《大数据算法》(王志宏 哈尔滨工业大学)31页
问题描述
给定一个数据流,从这个流中进行均匀采样。
要求在接收到n个数据后,能够等概率地输出其中的k个数据。
已知n远大于k,且现有的内存空间无法容纳所有数据。
算法描述
准备一个长度为k的数组用于保存样本。
将接收到的前k个数据保存在数组中,然后对于后续的第i个数据(i > k),掷出一个1~i之间的随机数j。
如果j<=k,则用第i个数据替换数组中第j个数据;否则。则舍弃第i个数据。
这样在接收到多于k个数据后,数组中保留的数据即为当前已接收数据的一个均匀抽样。
算法分析
按照常规的做法,保留n个数据然后从中均匀抽取k个样本,每个数据被抽取的概率为
那么当前这个问题的算法也要保证每个数据被留在数组中的概率为k/n。
假设已经获得了前(n-1)个数据的k个均匀抽样,现在再加入第n个数据,则第n个数据应该有k/n的概率被保留到数组。
而数组中原有的数据,被替换掉的概率为
再算上它们之前被选取为样本的概率k/(n-1),此时每个原有数据被保留下来的概率为
可见对于新数据和原有数据来说,它们被保留为样本的概率都是相同的。
那么前(n-1)个数据的k个均匀抽样要如何获得呢?这里可以令n = k+1,此时n-1=k,k个样本是唯一确定的。
借助上述算法就可以得到k+1个数据的均匀抽样。循环利用上述算法就能进一步得到前k+2、k+3、k+4个数据的均匀抽样,由此可以推广到任意n > k的情景。
算法的有效性得以证明。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步