背景
给定一个概率分布:[1/2, 1/3, 1/12, 1/12],我要你根据这个概率分布,随机抽取一个事件出来。有人说,直接用np.random.choice不就完了嘛,哈哈,确实如此,但是我们现在是在学习的过程,所以假设不允许你使用这个函数,必须自己写一个,只允许你均分分布地随机生成一个数,其他的内置采样函数不允许你使用。
普通算法
我们可以将其对应到线段上。
此时变成了[1/2,5/6,11/12,1]。那么我们可以随机生成一个数,然后,查找其所在的位置。学过数据结构的都知道,在一个长度为n(我们这里为4)的数组中,查找的复杂度为o(n),但是呢,由于我们这里是排好了序的,所以可以使用二分查找,复杂度为o(logn)。
别名采样方法
别名采样方法可以分为两部:
- 做表
- 根据表采样
1. 将概率分布的每个概率乘上N,画出柱状图。N为事件数量。为什么乘以N你可以最后慢慢体会其奥妙。
此时这些颜色的总面积为N,可以看出某些位置面积大于1某些位置的面积小于1。
将面积大于1的事件多出的面积补充到面积小于1对应的事件中,以确保每一个小方格的面积为1,同时,保证每一方格至多存储两个事件,这样我们就能看到一个1*N的矩形啦。
可以看到,上面这个图有一个特点,那就是最底层都是原来的那个事件,头上可能会有其他事件。
然后我们根据上面这个图得到两个数据结构。
- 原来的那个事件[2/3,1,1/3,1/3]。表示1事件在第1列所占比例为2/3,。。。
- 头上可能会有其他事件[2,没有,1,1]。表示第1列头上是2事件,。。。
2. 做好了这一个表之后,我们就可以坐享其成了。我们只需要产生两个随机数,第一次是均匀分布随机生成[1,N]之间的整数,用来决定落在哪一列,然后再生成一个[0,1]之间的小数,来决定要原来的那个事件还是头上的那个事件。
参考:
https://www.cnblogs.com/Lee-yl/p/12749070.html
https://blog.csdn.net/haolexiao/article/details/65157026