蓄水池抽样(原理&实现)
前言:
蓄水池抽样:从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和2,直到结束。最后集合
中剩下的就是保证随机抽取的
个元素。
蓄水池抽样算法正确性证明:
为了证明该算法的正确性,我们要保证算法结束后,原个元素每一个最后存活下来的概率都是
(因为从
个元素中随机抽取
个元素,每个元素被抽中的概率都是
)。形式化地,我们要证明的结论是:在算法的第i(0<=i<=n-k)轮,前k+i个元素每一个存活下来的概率是k/k+i 。
数学归纳证明:
当时,结论显然成立。
当时,根据算法,元素
存活的概率为
。而对于元素
,有两种情况会使其存活下来:要么元素
直接被淘汰;要么元素
留下,但是没有替换掉元素
。由归纳假设,
时结论成立,故元素
存活的概率为
,得证
举例描述辅助数学证明:
每次都是以 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 故证明成立!!!
实现代码和伪代码类似,就不赘述了
蓄水池抽样(原理&实现)的更多相关文章
- Reservoir Sampling - 蓄水池抽样
问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...
- Reservoir Sampling - 蓄水池抽样问题
问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...
- 【算法34】蓄水池抽样算法 (Reservoir Sampling Algorithm)
蓄水池抽样算法简介 蓄水池抽样算法随机算法的一种,用来从 N 个样本中随机选择 K 个样本,其中 N 非常大(以至于 N 个样本不能同时放入内存)或者 N 是一个未知数.其时间复杂度为 O(N),包含 ...
- Reservoir Sampling - 蓄水池抽样算法&&及相关等概率问题
蓄水池抽样——<编程珠玑>读书笔记 382. Linked List Random Node 398. Random Pick Index 从n个数中随机选取m个 等概率随机函数面试题总结 ...
- leetcode398 and leetcode 382 蓄水池抽样算法
382. 链表随机节点 给定一个单链表,随机选择链表的一个节点,并返回相应的节点值.保证每个节点被选的概率一样. 进阶:如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现? 示 ...
- C#LeetCode刷题-蓄水池抽样
蓄水池抽样篇 # 题名 刷题 通过率 难度 382 链表随机节点 47.0% 中等 398 随机数索引 41.6% 中等
- 【数据结构与算法】蓄水池抽样算法(Reservoir Sampling)
问题描述 给定一个数据流,数据流长度 N 很大,且 N 直到处理完所有数据之前都不可知,请问如何在只遍历一遍数据(O(N))的情况下,能够随机选取出 m 个不重复的数据. 比较直接的想法是利用随机数算 ...
- C# 蓄水池抽样
蓄水池采样算法解决的是在给定但长度未知的大数据集中,随机等概率抽取一个数据.如果知道数据的长度,可以用随机数rand()%n得到一个确切的随机位置,或者分块取值来构造随机,那么该位置的对象就是所求的对 ...
- Reservoir Sampling 蓄水池抽样算法,经典抽样
随机读取数据,如何保证真随机是不可能的,因为计算机的随机函数是伪随机的. 但是在不考虑计算机随机函数的情况下,如何保证数据的随机采样呢? 1.系统提供的shuffle函数 C++/Java都提供有sh ...
随机推荐
- IPv4地址学习总结
一. IPv4地址格式 网络互连的一个重要前提条件是要有一个有效的地址结构,并且所有的互连网络用户都应遵守这个地址结构.因为只有这样所有的互连网络用户才能在统一的规定下相互之间通讯.这个地址结构可以有 ...
- 使用bootstrap table小记(表格组件)
前言 新的一年悄然到来,生活依旧.最近一周大热的赵雷风,一首<成都>,一首<理想>再次把民谣展示在国人面前.歌词着实写的不错. 理想,你今年几岁 你总是诱惑着年轻的朋友 你总是 ...
- java byte【】数组与文件读写
此文全文参考http://blog.csdn.net/sniffer_wang/article/details/7455701,自己加以改进应用,谢了 import java.io.ByteArray ...
- JavaSE学习笔记
1.数据类型 boolean char byte short int long double float double array class interface 总结: 前9种基本类型,后3中引用类 ...
- V3学院XILINX FPGA寒假班培训感受 江苏大学 电子信息科学与技术 邓普建
事先申明一点,我是大一的学生,因此会站在一个新生的角度叙述. 刚开始接触V3学院是在江苏大学与V3学院合办的FPGA/SOC培训中,那是对全校开放的免费培训,历时三个周末.我那时有幸从头听到了尾,觉得 ...
- 缓冲流自动把getchar()填充
#include"stdio.h" #include"conio.h" #include<stdlib.h> int main() { char c ...
- 杭电2000——ASCII码排序
/* ASCII码排序 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- iOS开发之Runtime常用示例总结
经常有小伙伴私下在Q上问一些关于Runtime的东西,问我有没有Runtime的相关博客,之前还真没正儿八经的总结过.之前只是在解析第三方框架源码时,聊过一些用法,也就是这些第三方框架中用到的Runt ...
- Qt中纯C++项目发布为dll的方法(超详细步骤)
众所周知,我们可以将C++项目中的类以及某些方法导出,形成 .dll 文件,以供其他程序使用,下面将说明Qt环境下的使用方法. 首先创建共享库,步骤如下: 下一步会出现类对话框等等,不用管它,直接点击 ...
- 新手学js的效果图1---( 淘宝等商城货物查看特效)
本人结合之前所学一起写了,多个特效,只是新手自己瞎鼓捣的,思路清晰,具体实现的货物放大镜等,替换当中的img地址就可以查看特效 <!DOCTYPE html> <html lang= ...