算法系列:Reservoir Sampling
copyright © 1900-2016, NORYES, All Rights Reserved.
http://www.cnblogs.com/noryes/
欢迎转载,请保留此版权声明。
---------------------------------------------------------------------------------------
问题
随机抽样问题表示如下:
要求从N个元素中随机的抽取k个元素,其中N无法确定。
这种应用的场景一般是数据流的情况下,由于数据只能被读取一次,而且数据量很大,并不能全部保存,因此数据量N是无法在抽样开始时确定的;但又要保持随机性,于是有了这个问题。所以搜索网站有时候会问这样的问题。
这里的核心问题就是“随机”,怎么才能是随机的抽取元素呢?我们设想,买彩票的时候,由于所有彩票的中奖概率都是一样的,所以我们才是“随机的”买彩票。那么要使抽取数据也随机,必须使每一个数据被抽样出来的概率都一样。
解答
解决方案就是蓄水库抽样(reservoir sampling)。主要思想就是保持一个集合(这个集合中的每个数字出现),作为蓄水池,依次遍历所有数据的时候以一定概率替换这个蓄水池中的数字。
其伪代码如下:
for i= k+1 to N
M=random(1, i);
if( M <= k)
SWAP the Mth value and ith value
end for
解释一下:程序的开始就是把前k个元素都放到水库中,然后对之后的第i个元素,以k/i的概率替换掉这个水库中的某一个元素,所以每个元素被替换的概率是 1/i。
证明
用数学归纳法证明,我们的初始状态是i = k + 1
我们取了前k个数,显然初始状态这k个数的存在概率是1。
当i = k + 1时,k+1这个数以k/(k+1) 被选中去替换前k个数中的某一个。这个操作已经保证k+1这个数字是以概率k/(k+1)被保留。所以我们要证明的就是前k个数也是以k/(k+1)的概率被保留。对于这k个数中的任意一个都有两种情况,1.替换发生(k+1这个数被选中了) 2.替换没发生
我们随意取 1=< j <= k 来求第j个数的保留概率。那么根据全概率公式
P(j) = P(j | 替换发生) * P(替换发生)+ P(j | 替换没发生) * P(替换没发生)
P(替换发生) = k/(k+1) P(替换没发生) = 1/(k+1)
P(j | 替换发生) = (k-1)/k 因为在替换发生的条件下有1/k的概率j被替换掉了
P(j | 替换没发生) = 1 原来前k个数都以1概率存在
所以
P(j) = P(j | 替换发生) * P(替换发生)+ P(j | 替换没发生) * P(替换没发生)
= (k-1)/k * k/(k+1) + 1 * 1/(k+1)
= k / (k+1)
因为j是任意取值的所以得证。
接下来我们假设 i = n 时成立, 我们来证明i = n + 1的情况
既然i = n 时成立,所以 i = n 时任意一个数 1 <= j <= n 都以概率 k/n 出现在结果集中。
同理因为第n + 1个数以概率k/(n+1) 选中,所以无需考虑第n + 1 这个数,我们只要考虑前n个数中的任一个1 <= j <= n 在结果集中出现的概率
依然还是:
P(j) = P(j | 替换发生) * P(替换发生)+ P(j | 替换没发生) * P(替换没发生)
P(替换发生) = k/(n+1) P(替换没发生) = (n+1-k)/(n+1)
P(j | 替换发生) = k/n * (k-1)/k 因为在替换发生的条件下有1/k的概率j被替换掉了
P(j | 替换没发生) = k/n 前n个数都以k/n概率存在
P(j) = P(j | 替换发生) * P(替换发生)+ P(j | 替换没发生) * P(替换没发生)
= k/(n+1) * k/n * (k-1)/k + k/n * (n+1-k)/(n+1)
= k*(k-1)/(n*(n+1)) + k*(n+1-k)/(n*(n+1))
= k*(k-1+n+1-k)/(n*(n+1))
= k/(n+1)
算法系列:Reservoir Sampling的更多相关文章
- 蓄水池采样算法(Reservoir Sampling)
蓄水池采样算法 问题描述分析 采样问题经常会被遇到,比如: 从 100000 份调查报告中抽取 1000 份进行统计. 从一本很厚的电话簿中抽取 1000 人进行姓氏统计. 从 Google 搜索 & ...
- Spark MLlib之水塘抽样算法(Reservoir Sampling)
1.理解 问题定义可以简化如下:在不知道文件总行数的情况下,如何从文件中随机的抽取一行? 首先想到的是我们做过类似的题目吗?当然,在知道文件行数的情况下,我们可以很容易的用C运行库的rand函数随机的 ...
- 【数据结构与算法】蓄水池抽样算法(Reservoir Sampling)
问题描述 给定一个数据流,数据流长度 N 很大,且 N 直到处理完所有数据之前都不可知,请问如何在只遍历一遍数据(O(N))的情况下,能够随机选取出 m 个不重复的数据. 比较直接的想法是利用随机数算 ...
- 蓄水池算法(Reservoir Sampling)
蓄水池算法是一种随机算法,可以形象的描述为从一个n维的list中选取k个元素,其中n是一个很大的数或者n是一个未知的数,而且一般n很大使得不会将list存在主存中. 解法: i = 0 while m ...
- 【算法34】蓄水池抽样算法 (Reservoir Sampling Algorithm)
蓄水池抽样算法简介 蓄水池抽样算法随机算法的一种,用来从 N 个样本中随机选择 K 个样本,其中 N 非常大(以至于 N 个样本不能同时放入内存)或者 N 是一个未知数.其时间复杂度为 O(N),包含 ...
- 蓄水池抽样算法 Reservoir Sampling
2018-03-05 14:06:40 问题描述:给出一个数据流,这个数据流的长度很大或者未知.并且对该数据流中数据只能访问一次.请写出一个随机选择算法,使得数据流中所有数据被选中的概率相等. 问题求 ...
- Reservoir Sampling 蓄水池采样算法
https://blog.csdn.net/huagong_adu/article/details/7619665 https://www.jianshu.com/p/63f6cf19923d htt ...
- 水塘抽样(Reservoir Sampling)问题
水塘抽样是一系列的随机算法,其目的在于从包含n个项目的集合S中选取k个样本,其中n为一很大或未知的数量,尤其适用于不能把所有n个项目都存放到主内存的情况. 在高德纳的计算机程序设计艺术中,有如下问题: ...
- Reservoir Sampling - 蓄水池抽样问题
问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...
随机推荐
- tornado + supervisor + nginx 的一点记录
看了比较多的blog基本都是这个架构: supervisor ------------ app1 |-------app2 |-------.... |-------appn |-------ngin ...
- Tomcat端口占用
Tomcat端口占用问题 1.打开cmd,运行 netstat -aon!findstr "8080"查看该端口中运行的服务: 2.运行taskkill /pid PID /F 强 ...
- 数论v2
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> # ...
- redis安装与参数说明
redis安装与参数说明 博客分类: redis redis 1.下载tcl8.6.1-src.tar.gz 和 redis-2.8.6.tar.gz: 2.安装: 1).安装tcl Java代码 收 ...
- devstack meaning of: n-cond, n-novnc and n-xvnc
devstack has shortened names for a number of services, e.g. g-api = glance api g-reg = glance regist ...
- java mail api 使用
所需要的jar包: http://pan.baidu.com/s/1qWGZRJm 如果遇到这个错误:在windows防火墙允许 javaw.exe访问网络.或者关闭防火墙 FATAL ERROR i ...
- 关于TortoiseSVN的一些知识
TortoiseSVN的一切命令都是相对于它自己来说的 1.Import,导入,指的是导入SVN的代码库,即Repository. 2.Export,导出,指的是将代码从Repository中导出到你 ...
- java入门 第一季4
1.数组 1).声明数组 数据类型[]数组名; 数据类型 数组名[]; 2).分配空间 数组名=new 数据类型[数组长度]: 3).赋值 score[0]=98: 直接创建一个长度为4的数组 int ...
- Divide and conquer:Drying(POJ 3104)
烘干衣服 题目大意:主人公有一个烘干机,但是一次只能烘干一件衣服,每分钟失水k个单位的水量,自然烘干每分钟失水1个单位的水量(在烘干机不算自然烘干的那一个单位的水量),问你最少需要多长时间烘干衣服? ...
- jQueryUI Datepicker的使用
jQueryUI Datepicker是一个高度可定制的插件,可以很方便的为你的页面添加日期选择功能,你可以自定义日期的显示格式 以及要使用的语言. 你可以使用键盘的快捷键来驱动datepicker插 ...