如何有效地对连续负二项分布进行采样?

时间:2016-11-23 23:23:53

标签: random statistics

首先,对于上下文,我正在制作一个游戏,当你做一些好事时,你会获得积极的积分,当你做坏事时,你会获得负积分,而每个积分相当于翻转有偏见的硬币,如果你得到了头有些事情会发生(如果它是积极的信用就会很好,如果是负面的信用就会很糟糕),否则什么都不会发生。

这笔交易是我想要处理多个学分和小数学分的情况,我希望翻转使用学分,这样如果发生好/坏的事情,那么剩下的学分就会结转。一种直接的方法就是执行一系列试验,特别是对于分数信用的情况,我们可以将信用数乘以X和发生事件的可能性乘以1 / X(分布具有相同的期望)但重量略有不同);不幸的是,这实际上限制了用户可以获得多少学分,以及学分中可以有多少小数位数,因为这会导致无限量的工作。

我想要做的是利用我正在对连续负二项分布进行抽样的事实,这是获得头部所需的试验次数的分布,即如果f(X)是然后f(X)给出了在我们遇到头之前会有X尾的概率,其中X不必是整数。如果我可以对此分布进行采样,那么我可以做的是,如果X是尾部的数量,那么我可以看到X是否大于或小于信用数量;如果它大于那么我们用完了所有的学分,但什么也没发生,如果它小于或等于那么好事就会发生,我们从学分数中减去X.此外,由于分布是连续的,我可以轻松处理小数学分。

有没有人知道我能够有效地对连续负二项分布进行采样的方法(即,从该分布中生成随机数的函数)?

1 个答案:

答案 0 :(得分:2)

这个问题在StatsExchange上可能会得到更好的回答,但在这里我会对它进行一次尝试。

你是正确的,试图直接计算这将是计算上昂贵的,因为你无法避免beta和/或gamma函数依赖。我所知道的唯一统计上有效的近似值是,如果所需的成功次数s很大,且p既不是非常小也不是非常大,那么您可以使用正态分布来近似它具有平均值和方差的特殊值。您可以阅读更多here,但我猜这种近似通常不适合您。

负二项分布也可以近似为泊松分布的混合,但这并不能避免伽玛函数的依赖。

我所知道的唯一有效的负二项式采样器类使用优化的接受拒绝技术。本PDF here的第10-11页描述了该方法背后的概念。本PDF here的第6页(内部第295页)包含使用相关技术对二项式偏差进行采样的源代码。请注意,即使这些方法仍然需要随机统一偏差以及sqrt()log()gammln()调用。对于少量的试验(可能少于100次?),如果用快速随机数发生器模拟试验比甚至接受拒绝技术更快,我也不会感到惊讶。绝对是从快速PRNG开始;它们并非都是平等的。

修改

只要p 非常大(太接近1.0),以下伪代码绘制随机离散负二项分布值可能相当有效。它将返回到达您的第一个"期望"之前所需的试验次数。结果(实际上是第一个"失败"就分配而言):

// assume p and r are the parameters to the neg. binomial dist.
// r = number of failures (you'll set to one for your purpose)
// p = probability of a "success"
double rnd = _rnd.nextDouble(); // [0.0, 1.0)
int k = 0;  // represents the # of successes that occur before 1st failure
double lastPmf = (1 - p)^r;
double cdf = lastPmf;
while (cdf < rnd)
{
    lastPmf *= (p * (k+r) / (k+1));
    cdf += lastPmf;
    k++;
}
return k;
// or return (k+1) to also count the trial on which the failure occurred

使用递归关系可以节省在每一步独立重复因子的过程。我认为使用它,结合将小数精度限制为1或2位小数(因此您只需要分别乘以10或100)可能适用于您的目的。你只绘制一个随机数,其余的只是乘法 - 它应该非常快。