alias sample method——运行时间复杂度为O(1)的抽样算法
根据离散离散概率分布抽样是一个常见的问题。这篇文章将介绍运行时间复杂度为O(1)的 alias method 抽样算法思想。
下面举例说明:
比如 a,b,c,d 的概率分别为 0.1,0.2,0.3,0.4。如何编程实现按概率抽样呢?
最简单的方法是生成一个数组:1,2,2,3,3,3,4,4,4,4。然后随机生成一个不大于4的数。这种方法简单易实现,但当随机变量很多时,占用的空间就太大了。
再进一步,可以根据它们的概率密度分布(PDF)生成累积分布(CDF):0.1,0.3,0.6,1。然后生成不大于1的随机数,看它落在哪个区间。但这需要与临界点进行比较,
我们知道,插入有序数列最好的时间复杂度为O(logn)。
而alias method可以实现以运行复杂度为O(1)的方式抽样。当然它需要预处理,预处理的时间复杂度为O(n),但实际过程中,尤其是重复跑的时候,运行时间复杂度才是重要的。
alias method 怎么处理的呢?我们知道等概率分布抽样的时间复杂度为O(1),如果二项不等概率分布抽样的时间复杂度也为O(1)。如果a,b,c,d 概率分布均为0.25,那我们随机
生成1,2,3,4,抽中哪个就是哪个,复杂度自然为O(1)。如果只有两个变量,比如 a,b 概率分布为 0.2,0.8.那我们用CDF的方法,小于0.2就是a, 大于就是b,只需比较一次,
所以复杂度也是O(1)。alias method就是把这两种方法结合起来.
首先我们把原概率分布乘以N(为后面的拼接做准备),这里是N=4。得到:0.4,0.8,1.2,1.6。
然后我们把它拼成等概率分布和二项不等概率分布:
注意拼接的过程中,最多每一列最多有两种颜色。乘以N就保证了一定可以存在这样的拼法。具体证明见引用[1],图片出自引用[2]。
怎么抽样呢?
首先我们以等概率分布抽每一列。不失一般性,假设我们抽中了第三列。然后进行二项分布抽样,如果小于0.6,就是褐色,也就是c,反之,就是红色,也就是d.
这两个操作的复杂度均为O(1),故总时间复杂度也为O(1)。
怎么保证正确性呢?
以样本d,举例,原来抽中c的概率为0.4。运用alias method方法后,抽中c的概率为(0.25+ 0.25 * 0.2 + 0.25 * 0.4) = 0.4。事实上,等比例放大后再拆分,
其概率分布比例并没有变,结果当然也不会变。具体证明见引用[1].
引用:
1, http://www.keithschwarz.com/darts-dice-coins/
2, http://blog.csdn.net/sky_zhe/article/details/10051967
alias sample method——运行时间复杂度为O(1)的抽样算法的更多相关文章
- 时间复杂度为O(nlogn)的LIS算法
时间复杂度为 n*logn的LIS算法是用一个stack维护一个最长递增子序列 如果存在 x < y 且 a[x] > a[y],那么我们可以用a[y]去替换a[x] 因为a[y]比较小 ...
- 时间复杂度为O(nlogn)的排序算法
时间复杂度为O(nlogn)的排序算法(归并排序.快速排序),比时间复杂度O(n²)的排序算法更适合大规模数据排序. 归并排序 归并排序的核心思想 采用"分治思想",将要排序的数组 ...
- Alias sample(别名采样)
应用场景:加权采样,即按照随机事件出现的概率抽样 具体算法: 举例如上,随机事件出现的概率依次是1/2,1/3,1/12,1/12;记随机事件的个数为N,则所有事件概率乘以N后概率为2,4/3,1/3 ...
- 平均时间复杂度为O(nlogn)的排序算法
本文包括 1.快速排序 2.归并排序 3.堆排序 1.快速排序 快速排序的基本思想是:采取分而治之的思想,把大的拆分为小的,每一趟排序,把比选定值小的数字放在它的左边,比它大的值放在右边:重复以上步骤 ...
- Java虚拟机运行时数据区域及垃圾回收算法
程序计数器 记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空). Java 虚拟机栈 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口 ...
- (转)递归算法的时间复杂度终结篇与Master method
开篇前言:为什么写这篇文章?笔者目前在学习各种各样的算法,在这个过程中,频繁地碰到到递归思想和分治思想,惊讶于这两种的思想的伟大与奇妙的同时,经常要面对的一个问题就是,对于一个给定的递归算法或者用分治 ...
- python-Day5-深入正则表达式--冒泡排序-时间复杂度 --常用模块学习:自定义模块--random模块:随机验证码--time & datetime模块
正则表达式 语法: mport re #导入模块名 p = re.compile("^[0-9]") #生成要匹配的正则对象 , ^代表从开头匹配,[0 ...
- 关于乱序(shuffle)与随机采样(sample)的一点探究
最近一个月的时间,基本上都在加班加点的写业务,在写代码的时候,也遇到了一个有趣的问题,值得记录一下. 简单来说,需求是从一个字典(python dict)中随机选出K个满足条件的key.代码如下(py ...
- java.lang.reflect.Method.getAnnotation()方法示例【通过反射获取到方法对象再获取方法对象上的注解信息】
转: java.lang.reflect.Method.getAnnotation()方法示例 java.lang.reflect.Method.getAnnotation(Class <T&g ...
随机推荐
- Android Phonebook编写联系人UI加载及联系人保存流程(二)
2014-01-06 17:18:29 1. Phonebook中新建/编辑联系人的UI不是用xml文件写的,它是随着帐号类型的改变来加载不同的UI,比如SIM联系人,只有Name.Phone Num ...
- HQL查询及Hibernate对c3p0连接池的支持
//HQL查询 // auto-import要设置true,如果是false,写HQL时要指定类的全名 //查询全部列 Query query = session.createQuery(" ...
- windows下安装openssh服务并实现远程登录
需要准备的工具: winscp 点击下载 openssh 点击下载 步骤: 在远程计算机安装 1.首先安装openssh,双击并安装 2.指定用户的home directory为C:\ ...
- HTML参考
HTML Basic Document <html> <head> <title>Document name goes here</title> < ...
- sql 语句中使用条件判断case then else end
sql 语句中使用条件判断case then else end范例: SELECT les.[nLessonNo] FROM BS_Lesson AS les WHERE les.[sClassCod ...
- 数组包含字典-根据key排序
NSArray *array = [NSArray array]; [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id ...
- 内部类中class声明地方不同,效果不一样
1.一个声明在类中,一个声明在类的方法中.在类中的方法中声明内部类,其方法中的内部类调用 内部类外中的变量,变量必须final class Outter{ int x1 = 0; public voi ...
- 一个有趣的IE内核检测网站
http://se.360.cn/v5/iecoretest.html 该网站能有效检测您浏览器的内核,以及版本,操作系统. 找到这个网址,是因为最近解决WebBrowser自动调节IE版本功能时发现 ...
- JS 基础事件的用法
// 1.9以上用on // 案例一 // $('#btn').on('click', function(){ // //console.log(1); // alert('测试...'); // } ...
- java获取获得Timestamp类型的当前系统时间。
java获取获得Timestamp类型的当前系统时间. java获取取得Timestamp类型的当前系统时间 格式:2010-11-04 16:19:42 方法1: Timestamp d = n ...