Alias 采样及其Python实现

本文介绍了一种名为Alias Method的时间复杂度O(1)的离散采样算法,该算法能够生成符合特定概率分布的随机样本。通过两次掷骰子的比喻,文章详细解释了算法流程,包括事件概率的归一化、Alias表的构造方法以及如何使用两个队列进行Alias Table的构造,最后给出了Python实现代码。

Alias 采样

参考:【数学】时间复杂度O(1)的离散采样算法—— Alias method/别名采样方法
原文:关于数学理论

对于问题:
比如一个随机事件包含四种情况,每种情况发生的概率分别为: 1 2 , 1 3 , 1 12 , 1 12 \frac{1}{2},\frac{1}{3},\frac{1}{12},\frac{1}{12} 21,31,121,121,问怎么用产生符合这个概率的采样方法。

在这里插入图片描述

两次掷骰子:第一次决定所属列,第二次决定事件概率。

算法流程

  1. 事件N中情况概率按照均值归一化,即每种情况概率乘N。
    在这里插入图片描述

  2. 构造Alias表。
    Alias Method一定要保证:每列中最多只放两个事件;
    在这里插入图片描述

  3. 按照某种方法将整个概率分布拉平成为一个1*N的长方形即为Alias Table,然后储存两个数组,一个里面存着第i列对应的事件i矩形所占的面积百分比,即概率,上图的话数组就为 P r o b [ 2 3 , 1 , 1 3 , 1 3 ] Prob[\frac{2}{3}, 1, \frac{1}{3}, \frac{1}{3}] Prob[32,1,31,31]。另一个数组里面储存着第i列不是事件i的另外一个事件的标号,上图就是Alias[2,NULL,1,1]

Alias Table构造方法

用两个队列A,B去储存面积大于1的节点标号,和小于1的节点标号,每次从两个队列中各取一个,将大的补充到小的之中,小的出队列,再看大的减去补给之后,如果大于1,继续放入A中,如果等于1,则也出去,如果小于1则放入B中。算法复杂度为O(n)。

python代码

class AliasSampling:
    """Helper function for performing sampling."""
    def __init__(self, prob):
        self.n = len(prob)
        self.U = np.array(prob) * self.n
        self.K = [i for i in range(len(prob))]
        overfull, underfull = [], []
        for i, U_i in enumerate(self.U):
            if U_i > 1:
                overfull.append(i)
            elif U_i < 1:
                underfull.append(i)
        while len(overfull) and len(underfull):
            i, j = overfull.pop(), underfull.pop()
            self.K[j] = i
            self.U[i] = self.U[i] - (1 - self.U[j])
            if self.U[i] > 1:
                overfull.append(i)
            elif self.U[i] < 1:
                underfull.append(i)

    def sampling(self, n=1):
        x = np.random.rand(n)
        i = np.floor(self.n * x)
        y = self.n * x - i
        i = i.astype(np.int32)
        res = [i[k] if y[k] < self.U[i[k]] else self.K[i[k]] for k in range(n)]
        if n == 1:
            return res[0]
        else:
            return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值