Reservoir Sampling - 蓄水池抽样

2023-10-08 09:20

本文主要是介绍Reservoir Sampling - 蓄水池抽样,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

问题起源于编程珠玑,其描述如下:

  How could you select one of n objects at random, where you see the objects sequentially but you do not know the value of n beforehand? For concreteness, how would you read a text file, and select and print one random line, when you don’t know the number of lines in advance?

  问题定义可以简化如下:在不知道文件总行数的情况下,如何从文件中随机的抽取一行?

  首先想到的是我们做过类似的题目吗?当然,在知道文件行数的情况下,我们可以很容易的用C运行库的rand函数随机的获得一个行数,从而随机的取出一行,但是,当前的情况是不知道行数,这样如何求呢?我们需要一个概念来帮助我们做出猜想,来使得对每一行取出的概率相等,也即随机。这个概念即蓄水池抽样(Reservoir Sampling)

  有了这个概念,我们便有了这样一个解决方案:定义取出的行号为choice,第一次直接以第一行作为取出行 choice ,而后第二次以二分之一概率决定是否用第二行替换 choice ,第三次以三分之一的概率决定是否以第三行替换 choice ……,以此类推,可用伪代码描述如下:

i = 0

while more input lines

           with probability 1.0/++i

                   choice = this input line

print choice

  这种方法的巧妙之处在于成功的构造出了一种方式使得最后可以证明对每一行的取出概率都为1/n(其中n为当前扫描到的文件行数),换句话说对每一行取出的概率均相等,也即完成了随机的选取。

  证明如下:

  回顾这个问题,我们可以对其进行扩展,即如何从未知或者很大样本空间随机地取k个数?

  类比下即可得到答案,即先把前k个数放入蓄水池,对第k+1,我们以k/(k+1)概率决定是否要把它换入蓄水池,换入时随机的选取一个作为替换项,这样一直做下去,对于任意的样本空间n,对每个数的选取概率都为k/n。也就是说对每个数选取概率相等。

  伪代码:

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 

  证明如下:

  

  蓄水池抽样问题是一类问题,在这里总结一下,并由衷的感叹这种方法之巧妙,不过对于这种思想产生的源头还是发觉不够,如果能够知道为什么以及怎么样想到这个解决方法的,定会更加有意义。


例题:有300,000员工,抽奖100,000人。现在只有一个rand(),其范围是0-65535.

想法就是储水池抽样,以m/n 等概率取得每个员工

//生成 0 - k(最大300,000)的随机数,需要19位int getRandk(int k) {int val, val2, ret = 300,000;while ( (ret) >= k) {val  = rand();//低16位val2 = rand(); //高16位ret = (val | (val2&7)<<16);}return ret;}//生成 0 - 100000的随机数,只要17位int getRand1() {int val, val2, ret = 300000;while ( (ret) >= 100000) {val  = rand();//低16位val2 = rand(); //高16位ret = (val | (val2&1)<<16);}return ret;}bool lucky(int k) {// m/k的概率决定是否留下if (k < 100000) { return true; }else{int t = getRandk(k);if (t < 100000) {return true;}}return false;}//rand(): 0 - 65535vector<int> getLuckyPeople() {vector<int> peoples;for (int i = 0; i < 300000; ++i) {if (lucky(i)) {if (peoples.size() == 100000) {//从100000里随机挑一个替换int t = getRand1();peoples[t] = i;continue;}peolpes.push_back(i);}}return peoples;}




参考文章:

http://www.cnblogs.com/HappyAngel/archive/2011/02/07/1949762.html

这篇关于Reservoir Sampling - 蓄水池抽样的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/164283

相关文章

398. Random Pick Index 382. Linked List Random Node 蓄水池原理

蓄水池原理应用: 随机返回n个元素中的某个元素,从0开始遍历这n个元素 用count记录遍历过得元素数目(符合要求的元素在数,比如数值等于target的数组索引),如果random(count)==0 则选中这个元素。 可以证明 在遍历的过程中 随着遍历元素数目的增加 random(count)==0  的几率是随机均等的 Given an array of integers

FouriDown: Factoring Down-Sampling into Shuffling and Superposing

摘要 https://openreview.net/pdf?id=nCwStXFDQu 空间下采样技术,如步长卷积、高斯下采样和最近邻下采样,在深度神经网络中至关重要。在本文中,我们重新审视了空间下采样家族的工作机制,并分析了先前方法中使用的静态加权策略所引起的偏差效应。为了克服这种偏差限制,我们提出了一种在傅里叶域中的新型下采样范式,简称FouriDown,它统一了现有的下采样技术。受信号采

点云处理中阶 Sampling

目录 一、什么是点云Sampling 二、示例代码 1、下采样  Downsampling 2、均匀采样 3、上采样 4、表面重建 一、什么是点云Sampling 点云处理中的采样(sampling)是指从大量点云数据中选取一部分代表性的数据点,以减少计算复杂度和内存使用,同时保留点云的几何特征和重要信息。常见的点云采样方法有以下几种: 随机采样(Random Samp

自然抽样和平顶抽样

自然抽样和平顶抽样是两种信号处理和采样技术,它们在音频信号处理、信号重建以及数字信号处理中有着不同的应用。 1. 自然抽样(也称为理想抽样或无失真抽样):样值脉冲的幅度随原始信号m(t)的幅度而变; 自然抽样过程的波形和频谱: 自然抽样与恢复原理框图: 恢复:均可通过理想低通滤波器恢复原始信号 在理想情况下,自然抽样是指将连续时间信号在某个特定频率下(通常称为奈奎斯特频率的两倍)

通信原理抽样定理和PAM调制解调硬件实验

一、实验目的 1. 加深理解抽样定理; 2. 加深理解脉冲幅度调制的原理。 二、实验内容 1. 观测PAM平顶抽样波形; 2. 观测PAM自然抽样波形及解码后波形。 三、实验器材 1. 双踪示波器; 2. 通信原理实验箱信号源模块、①号模块。 四、实验步骤 1. 观测PAM平顶抽样波形 (1)用示波器观测信号源“2K同步正弦波”输出,调节W1改变输出信号幅度,使输出信号峰峰值

压缩感知与Nquist抽样定理——模拟信息转换(AIC)学习总结

原文链接:http://blog.csdn.net/jbb0523/article/details/41595535 一、引言 压缩感知(CompressiveSensing, or Compressed Sensing)或译为压缩传感,或者称为压缩采样(Compressive sampling),以下统称压缩感知,简称CS。 在压缩感知的有关文献中几乎都在说“压缩感知突破了传统的Nq

大数据算法-空间时间亚线性算法举例(水库抽样,平面图直径)

大数据算法-空间时间亚线性算法举例 水库抽样 问题描述 Input:一组数据 Output:这组数据的K个均匀抽样要求: 扫描一次空间复杂度o(k)扫描到前n个数字时,保存当前数据的均匀抽样实现 收到第i个元素t时,以k/i的概率随机替换抽样数组ans[]中的元素证明 均匀: ki×(1−1i+1)×(1−1i+2)×⋯×(1−1n)=kn \frac{k}{i}\tim

Llama模型家族之拒绝抽样(Rejection Sampling)(九) 强化学习之Rejection Sampling

LlaMA 3 系列博客 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (三) 基于 LlaMA 3 + LangGraph 在windows本地部署大模型 (四) 基于 LlaMA 3

从0开始学统计-战斗机保护和代表性抽样

1.什么是抽样研究?为什么要做抽样研究? 抽样研究是一种研究方法,它涉及从整体人群或群体中选取一部分样本来代表整体,以进行研究和推断。在抽样研究中,研究者从总体中选择一个相对较小的样本,通过对这个样本进行观察、实验或调查来推断总体的特征、趋势或关系。 抽样研究的目的在于: (1)节省时间和成本: 通过研究样本而不是整个总体,可以节省大量的时间和资源。这样的方法通常更经济高效。 (2)可行性

蓄水池采样 Reservoir Sampling

# coding:utf8import random# 从n个数中采样k个数def reservoir_sampling(n, k):# 所有数据pool = [i for i in range(n)]# 前k个数据res = [i for i in range(k)]for i in range(k, n):v = random.randint(0, i)if v < k:res[v] =