蓄水池抽样(Reservoir Sampling)是一个很有趣的问题,它能够在o(n)时间内对n个数据进行等概率随机抽取,例如:从1000个数据中等概率随机抽取出100个。另外,如果数据集合的量特别大或者还在增长(相当于未知数据集合总量),该算法依然可以等概率抽样。

说蓄水池抽样之前,先说一下等概率随机抽取问题,等概率随机抽取是一个很有用的东西,因为在很多情况下,尤其是搞模式识别时,需要这个东西。比如,我们想从10000个样本中随机抽取5000个作为训练集,5000个作为测试集,那么等概率随机抽取便派上用场了。那么,究竟该如何做等概率随机抽取呢?一般的想法应该是,随机生成一个(0,n-1)之间的数x,然后抽取集合中第x个数据,如果本次生成的数x‘与之前某次生成的数x是相同的,那么继续随机生成,直到生成一个与之前所有生成过的数不同的数。并将这样的随机生成做m次。

这样做思路上是最简单的,但是问题却出现了,如果m比较小还好,比如n=10000,m=100,就是说10000个数里面随机挑100个,基本上没什么重合的概率,因为当做第100次随机生成时,之前才生成了99个,所以至多有99/10000≈1%的概率生成与之前重复的数。那么,我们可以很顺利的随机的、等概率的生成100个数,并且基本上只调用100次rand函数就行。但是如果m比较大呢?还是刚才那个例子,如果n=10000,m=5000呢?这涉及到一个求期望的问题,设sum为该算法调用rand函数的次数,我们来求一下E(sum),由于每次随机生成的数都是独立的,因此E(sum)=E(num1)+E(num2)+...E(numm),所以我们求出生成第x个数需要调用多少次rand函数即可。

假设前面已经生成了x个数,我们要生成第x+1个数,那么,有如下概率:

调用1次rand函数就成功生成该数的概率为:(1-x/n)

调用2次rand函数就成功生成该数的概率为:(1-x/n)*(x/n)

。。。

调用k次rand函数就成功生成该数的概率为:(1-x/n)*(x/n)^(k-1)

则E(numx)=1*(1-x/n)+2*(1-x/n)*(x/n)+...+k*(1-x/n)*(x/n)^(k-1)...

这个计算并不难,在此我仅给出我计算出的期望:n/(n-x)(默认x从0开始,程序员的习惯)

最后,E(sum)=n/n+n/(n-1)+n/(n-2)+....+n/(n-m+1)

这个期望就比较难算了,复杂度大概是O(n*(lg(n)-lg(n-m)))级别的。在n比较大,m也比较大的时候,这个规模比O(n)可大多了。因此,蓄水池抽样在这个时候就有优势了,而且,对于另一种比较变态的情况,假设n非常大,以至于我们并不知道n的确切数量,而且n还在动态的增长,我们要不停的随机等概率的抽取n的一定比例(例如10%),这种情况下,上面所介绍的普通抽样方法就很难做到了。

蓄水池抽样:从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

上述伪代码的意思是:先选中第1到k个元素,作为被选中的元素。然后依次对第k+1至第N个元素做如下操作:

每个元素都有k/x的概率被选中,然后等概率的(1/k)替换掉被选中的元素。其中x是元素的序号。

算法的成立是用数学归纳法证明的:

每次都是以 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的话,说明我们的算法是没有问题的。

对这个问题可以用归纳法来证明:k< i <=N1.当i=k+1的时候,蓄水池的容量为k,第k+1个元素被选择的概率明显为k/(k+1), 此时前k个元素出现在蓄水池的概率为 k/(k+1), 很明显结论成立。2.假设当 j=i 的时候结论成立,此时以 k/i 的概率来选择第i个元素,前i-1个元素出现在蓄水池的概率都为k/i。

证明当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故证明成立

个人觉得这个算法在模式识别中,对数据集做随机划分(划分为训练集和测试集)的时候非常好用,因为一来我不需要预先知道数据的总量,二来对于数据量很大的情况速度还是比第一种方法快的。正好之前需要写一个随机划分的程序,小试了一下,感觉还不错,代码如下:

主要功能:

输入一个包含2类的libsvm样式的样本集合文件,并制定需要随机提取的样本数量

输出随机提取的样本集合

RandomSelect.h

#include#include#include#include#include

using namespacestd;#define MAX_LENGTH 0x7fff

void reservoirSampling(long select_num,long* pos_select,long* neg_select,char*input_path);void saveFile(long select_num,long* pos_select,long* neg_select,char* input_path,char*ouput_path);void usage();

RandomSelect.cpp

/*Author: SongQi

Create Time:2012/9/19

Function: A program which can randomly select samples from the input sample file.

It can be used to seperate training samples and testing samples.Now it only can select two-class samples.

Input:

1.input sample file path 2.output sample file path 3.sample number need to select for each postive and negative samples.

Output:

1.output sample file*/#include"stdafx.h"#include"RandomSelect.h"#include

using namespacestd;int main(int argc, char**argv)

{//input sample file path

char* input_path =NULL;//output sample file path

char* ouput_path =NULL;//selected sample number from the input file

long select_num=0;if( argc != 4)

{

usage();

system("pause");return 0;

}else{

input_path=argv[1];

ouput_path=argv[2];

select_num=atol(argv[3]);

}long *pos_select=new long[select_num];long *neg_select=new long[select_num];//random select samples from the input file

reservoirSampling(select_num,pos_select,neg_select,input_path);

saveFile(select_num,pos_select,neg_select,input_path,ouput_path);

system("pause");return 0;

}void reservoirSampling(long select_num,long* pos_select,long* neg_select,char*input_path)

{

FILE*input_file=fopen(input_path,"r");if(input_file==NULL)

{

printf("the input sample file does not exist!\n");

usage();

system("pause");return;

}

fseek(input_file,0,SEEK_SET); //set to the start of the file

int label=0;long index=0;long pos_count =0;long neg_count =0;

srand( time(NULL) );charstuff;while(true)

{if(fscanf(input_file,"%d",&label)!=1)break;//printf("%d\n",label);RAND_MAX

if(label==0)

{if(neg_count

neg_select[neg_count]=index;else{long is_select=rand()%(neg_count+1)+1;if(is_select<=select_num)

neg_select[rand()%select_num]=index;

}

neg_count++;

}else{if(pos_count

pos_select[pos_count]=index;else{long is_select=rand()%(pos_count+1)+1;if(is_select<=select_num)

pos_select[rand()%select_num]=index;

}

pos_count++;

}//printf("pos:%dneg:%d\n",pos_count,neg_count);

index++;char* detect_buffer = new char[2]();while(strcmp(detect_buffer,"\n")!=0)

fread(detect_buffer,sizeof(char),1,input_file);

}

printf("%d\n",index);

FILE*out_file1=fopen("pos_index.txt","w");

FILE*out_file2=fopen("neg_index.txt","w");for(int i=0;i

{

fprintf(out_file1,"%d\n",pos_select[i]);

fprintf(out_file2,"%d\n",neg_select[i]);

}

fclose(out_file1);

fclose(out_file2);

fclose(input_file);

}void saveFile(long select_num,long* pos_select,long* neg_select,char* input_path,char*ouput_path)

{

ifstream fin(input_path);

FILE*output_file=fopen(ouput_path,"w");charline[MAX_LENGTH];long index=0;while( fin.getline(line, MAX_LENGTH))

{//printf("%s",line);

for(long count=0;count

{if(index==pos_select[count])

{

fprintf(output_file,"%s\n",line);

}if(index==neg_select[count])

{

fprintf(output_file,"%s\n",line);

}

}

index++;

}

fclose(output_file);return;

}voidusage()

{

printf("arg1:input sample file path\n");

printf("arg2:output sample file path\n");

printf("arg3:sample number need to select for each postive and negative samples\n");

}

蓄水池采样算法的python实现_蓄水池采样算法的python实现_蓄水池抽样及实现相关推荐

  1. python过采样代码实现_过采样中用到的SMOTE算法

    平时很多分类问题都会面对样本不均衡的问题,很多算法在这种情况下分类效果都不够理想.类不平衡(class-imbalance)是指在训练分类器中所使用的训练集的类别分布不均.比如说一个二分类问题,100 ...

  2. python生成簇_使用Python复现SIGKDD2017的PAMAE算法(并行kmedoids算法)

    作者:坚新 研究方向:自然语言处理 https://github.com/yangjianxin1/PAMAE 编者按:AINLP技术群的坚新同学发布了一个新项目:PAMAE (PAMAE: Para ...

  3. python数据结构与算法分析_数据结构与算法(Python版)

    为什么研究数据结构与算法 本周带大家进入Python版数据结构与算法的学习.想必大家都听过"算法"一词,算法的学习对编程者来说是至关重要的.首先我们先了解一下为什么要研究数据结构与 ...

  4. python多叉树遍历_基于Python的多叉树遍历算法

    [ 综直厘翹 S 赛理 ) 信息记录材料 2019 年 5 月第 20 卷第 5 期 基于 Python 的多叉树遍历算法 钱雨波 , 王金祥 ( 指导老师 ) ( 延边大学 吉林 延边 1 3300 ...

  5. Python用MCMC马尔科夫链蒙特卡洛、拒绝抽样和Metropolis-Hastings采样算法

    最近我们被客户要求撰写关于MCMC的研究报告,包括一些图形和统计输出. 我们将研究两种对分布进行抽样的方法:拒绝抽样和使用 Metropolis Hastings 算法的马尔可夫链蒙特卡洛方法 (MC ...

  6. python手写字母识别_机器学习--kNN算法识别手写字母

    本文主要是用kNN算法对字母图片进行特征提取,分类识别.内容如下: kNN算法及相关Python模块介绍 对字母图片进行特征提取 kNN算法实现 kNN算法分析 一.kNN算法介绍 K近邻(kNN,k ...

  7. python数独伪代码回溯法_数独 #回溯算法 #CTF

    1. intro:巅峰极客的一道逆向 刷巅峰极客2020里的rev题fu!kpy,复杂得不行但是看到if d[1][0] != '8' or d[1][7] != '2'和if check(h1) ! ...

  8. 人工鱼群算法python代码_人工鱼群算法python_鱼群算法 - Brillou的个人空间 - OSCHINA - 中文开源技术交流社区......

    本算法是参照李晓磊博士的论文实现的,详细的算法原理可阅读<一种新型的智能优化方法_人工鱼群算法_李晓磊> 算法基于鱼群的生存行为:在一片水域中,鱼存在的数目最多的地方就是本水域中富含营养物 ...

  9. rrt算法流程图_基于采样的路径搜索算法代码实现(RRT和PRM)

    1.采样法 利用网格法可以得到对特定离散化后C-space的最优解.但网格法的缺点是计算复杂度高,适用于自由度较低的机器人.本文简要介绍另一种基于采样的规划器,它涉及以下函数,通过这些函数构建一个图( ...

  10. python二分查找时间复杂度_二分查找算法的时间复杂度计算(logN)

    二分查找算法的时间复杂度计算(logN) 马富天 2019-08-10 20:25:24 54 [摘要]二分查找算法是对顺序查找算法的优化,二分查找算法的前提是数列是一个有序数列,递增或者递减,本文就 ...

最新文章

  1. Springboot引用外部配置文件
  2. Ubuntu14.04安装GitLab指南
  3. php不能加载oci8,无法加载动态库'oci8.so'(PHP 7.2)
  4. UOJ.117.欧拉回路
  5. MySQL5.7 semi-sync replication功能增强
  6. 资源下载!5本从Python入手机器学习的必备电子书!(附下载链接)
  7. 计算机在材料科学与工程中的应用,计算机在材料科学与工程中的应用
  8. insert执行成功 没有数据_Python—接口测试数据库封装实现原理
  9. Python-Matplotlib 12 多图figure
  10. 拓端tecdat|R语言自定义两种统计量度:平均值和中位数,何时去使用?
  11. Keil 5 C51与STM32
  12. 程序员在国外:在加拿大IT公司工作三年的一些感受
  13. Unity NavMesh寻路 A*(A star)分析及实例应用(一)
  14. 冒烟测试和回归测试的区别
  15. RFC8402 Segment Routing Architecture 翻译
  16. Linux死锁调试之softlockup
  17. 【西门子】S7-PLCSIM Advance_V2/V3, Error Code: -30,LicenseNotFound /NetGroup Packet Filter Driver (NPF)
  18. NLP之Common sense常识推理
  19. Python处理大学英语四级考试数据(Excel文件)案例一则
  20. Matlab实现DBSCAN算法(每行代码标注详细注解)

热门文章

  1. 轻言壁纸微信小程序源码
  2. 困在“墙”里的中年程序员
  3. b560主板怎么样 b560主板支持的cpu
  4. 华硕P8H61-M+i3-3220 +GTX650
  5. 简单制作一个Python聊天机器人
  6. 计算机组装防呆,电脑内存如果没有防呆口反插有什么后果?
  7. 以开发之名|线上家装新美学——梦想之家,由你来定
  8. 安卓 获取rtsp流 截屏_安卓星雨视频+星火电视盒子版+安卓文件闪传+安卓截屏大师...
  9. 人民大学与加拿大女王大学金融硕士——你终究会成为你想成为的人
  10. find the longest of the shortest HDU - 1595