算法系列: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 ...
随机推荐
- 【Other】Ubuntu 14.04 pptp 客户端连接配置
sudo apt-get install pptp-linux binutils modprobe ppp_mppe sudo pptpsetup --create testvpn --server ...
- JustMock Lite (Free Mocking Framework For .net)
通过 Nuget 安装 2. 官网下载(官网不行点这里) 3. 帮助文档 商业版和免费版区别概览 MockingContainer 测试类准备:一般来说也是业务类 public class C ...
- [转载]python gevent
原地址: http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001407503089 ...
- iOS 关于AFNetworking ssl 待完成
先普及下基本知识,都是从网上搜到的,感谢原作者的辛勤付出! 原文链接 http://m.blog.csdn.net/blog/bytxl/8586830 x509是数字证书的规范,P7和P12是两种封 ...
- MySQL排序原理与MySQL5.6案例分析【转】
本文来自:http://www.cnblogs.com/cchust/p/5304594.html,其中对于自己觉得是重点的加了标记,方便自己查阅.更多详细的说明可以看沃趣科技的文章说明. 前言 ...
- [转]Android 学习资料分享(2015 版)
转 Android 学习资料分享(2015 版) 原文地址:http://www.jianshu.com/p/874ff12a4c01 目录[-] 我是如何自学Android,资料分享(2015 版) ...
- suse linux 10 下配置vpn服务器(pptp)
一.安装所需的软件包: pptpd-*.rpm ppp-*.rpm pptp-*.rpm 一般情况下系统已经将pptp和ppp包安装好了,所以只需安装pptpd ...
- Python 开发轻量级爬虫03
Python 开发轻量级爬虫 (imooc总结03--简单的爬虫架构) 现在来看一下一个简单的爬虫架构. 要实现一个简单的爬虫,有哪些方面需要考虑呢? 首先需要一个爬虫调度端,来启动爬虫.停止爬虫.监 ...
- js验证手机号
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...
- 获取指定文件下的所有file文件
/** * 描述:获取所有的文件列表 * @param file * @param list * @return */ private List<File> getAllFiles(Fil ...