如何基于任意离散分布生成数字?


28

如何基于任意离散分布生成数字?

例如,我有一组要生成的数字。假设它们从1-3标记如下。

1:4%,2:50%,3:46%

基本上,百分比是它们将出现在随机数生成器的输出中的概率。我有一个伪随机数生成器,它将在间隔[0,1]中生成均匀分布。有什么办法吗?

我可以拥有多少个元素没有限制,但是%总计为100%。


2
我可能建议在标题中指定“ ...任意离散分布”,如果这是您的问题。连续的情况是不同的。
大卫·M·卡普兰

3
一个通用的方法是累积概率,其在该例子将是列表内执行二进制搜索(0,0.04,0.54,1.0)。平均而言,每个世代事件需要log(n)/2探测。如果没有概率是非常小的,就可以得到O(1)通过在创建等间距的值的矢量性能[0,1]和(在预计算阶段)分配的结果,以每个值。例如,在此示例中,您可以创建矢量(1,1,1,1,2,,2,3,,3)(具有50 2的和46 3的)。生成一个统一的乘以100,然后索引到该向量中:完成。
ub


该“此处”链接实际上链接到了这个问题,@Glen_b ...复制n粘贴错误?
buruzaemon

@buruzaemon谢谢,是的,这是一个错误;我已经改正了。
Glen_b-恢复莫妮卡

Answers:


26

从离散分布采样的最佳算法之一是别名方法

别名方法(有效地)预先计算二维数据结构,以将矩形划分为与概率成比例的区域。

数字

在从被引用的网站这个示意图,单元高度的矩形已经被划分为四种区域-通过颜色区分-在比例1 / 31 / 12,和1 / 12,在为了从具有这些概率的离散分布中重复采样。垂直条具有恒定的(单位)宽度。每个都分为一两部分。件的标识和垂直分隔的位置存储在可通过列索引访问的表中。1/21/31/121/12

该表可以通过两个简单步骤(每个坐标一个)进行采样,只需生成两个独立的统一值并进行计算。如此处其他答复中所述,这改善了反转离散CDF所需的O log n 计算。O(1)O(log(n))


2
仅当概率计算便宜时,此算法才是最佳算法。例如,如果很大,则最好不要构造整个树。n
概率

3
+1到目前为止,这是提出和描述一种有效算法的唯一答复。
ub

19

您可以在R中轻松完成此操作,只需指定所需的大小即可:

sample(x=c(1,2,3), size=1000, replace=TRUE, prob=c(.04,.50,.46))

3
就我个人而言,我更喜欢一种算法(或在某处学习必要的知识),因为我试图将其整合到我正在构建的应用程序中:)尽管非常感谢您的回答:)
FurtiveFelon 2012年

嗯,好的。。。多了解一些您想做的事情将有助于我们指导您。您能告诉我们更多吗?(目的,语境等)
Dominic Comtois 2012年

这是为了投票。例如,我有一堆照片,并且一次只能向用户显示6张照片,我想一次向用户显示“最佳”照片,并且用户可以对每张照片进行投票或否决。现在可以使用的最简单的解决方案是我概述的方案(每个数字代表一张照片,每一次否决票都将降低该照片的出现率,并增加其他所有内容)
FurtiveFelon 2012年

1
@furtivefelon,您总是可以从R移植代码,o从代码中找出算法并重新实现它。
mpiktas 2012年

我想您可能会在Stack Overflow上获得一些好的建议(更好的建议),因为可能有一些针对此特定目的的知名解决方案。我建议也将您上一次评论中的信息直接添加到您的问题中。
Dominic Comtois,2012年

19

在您的示例中,假设您绘制了伪随机Uniform [0,1]值并将其命名为U。然后输出:

如果U <0.04,则为1

如果U> = 0.04并且U <0.54,则为2

如果U> = 0.54,则为3

如果指定的百分比是a,b,...,则只需输出

如果U则为1

如果U> = a并且U <(a + b)则值为2

等等

本质上,我们将%映射到[0,1]的子集中,并且我们知道统一随机值落入任何范围的概率就是该范围的长度。排列范围似乎是最简单的方法,即使不是唯一的方法。假设您仅询问离散分布;对于连续性,可以执行“拒绝采样”之类的操作(Wikipedia条目)。


8
如果按概率降序对类别进行排序,则算法会更快。这样,您对每个生成的随机数进行的测试(平均)会更少。
jbowman

1
只是要对排序进行快速注释-仅当您在抽样方案开始时才进行一次排序,此方法才有效-因此,对于概率本身作为较大整体方案的一部分进行抽样的情况,这样做效果不佳(例如。然后p - [R Ý = Ĵ = p Ĵ)。通过在这种情况下进行排序,您可以将排序操作添加到每个采样迭代中-这将添加O n log n pĴ距离P[Rÿ=Ĵ=pĴØñ日志ñ每次迭代的时间。但是,在这种情况下,从一开始就对概率大小进行近似猜测可能会很有用。
概率

4

假设有可能的离散结果。你瓜分间隔[ 0 1 ]到基于累积概率密度函数,子区间˚F,得到分割0 1 的间隔m[0,1]F(0,1)

I1I2Im

其中˚F 0 0。在您的示例中m = 3并且Ij=(F(j1),F(j))F(0)0m=3

I1=(0,.04),     I2=(.04,.54),     I3=(.54,1)

因为F 2 = .54F 3 = 1F(1)=.04F(2)=.54F(3)=1

然后,您可以使用以下算法生成具有分布F的XF

(1)生成UUniform(0,1)

(2)如,则X = ĴUIjX=j

  • 通过查看是否小于每个累积概率,并查看变化点(从到),可以完成此步骤,这应该是在使用的任何编程语言中使用布尔运算符,以及查找向量中第一个出现的位置。UTRUEFALSEFALSE

注意,将在时间间隔中的恰好一个Ĵ,因为它们是不相交的和分区[ 0 1 ]UIj[0,1]


这些间隔不应该全部关闭吗?否则,不包括间隔之间的边界。{[0,0.04), [0.04,0.54), [0.54,1]}
naught101

1
对于任何点 u(即,半开区间的Lebesgue测度与开区间的相同),所以我认为这并不重要。P(U=u)=0u
2012年

1
但是,在有限精度的数字机器上,也许在宇宙终结之前的某天很重要……
jbowman 2012年

1
公平一点,@ whuber,请看我的编辑。
2012年

1
好的,那是一种算法。顺便说一句,你为什么不只返回类似的东西min(which(u < cp))?也最好避免在每次调用时重新计算累积和。使用该预先计算的方法,整个算法将简化为min(which(runif(1) < cp))。或者更好,因为OP要求生成数字(复数),所以将其向量化为n<-10; apply(matrix(runif(n),1), 2, function(u) min(which(u < cp)))
ub

2

一个简单的算法是从您的统一随机数开始,然后在循环中首先减去第一个概率,如果结果为负,则返回第一个值,如果结果仍为正,则转到下一个迭代并减去下一个概率,检查是否为负等。

这样做的好处是值/概率的数量可以是无限的,但是仅当您接近这些值时才需要计算概率(例如,根据泊松或负二项分布生成的概率)。

如果您有一组有限的概率,但将根据它们生成许多数字,则对这些概率进行排序可能会更有效,以便先减去最大的值,然后再减去第二个最大的值,依此类推。


2

首先,让我着重介绍一个python库,该具有随时可用的类,这些类可用于遵循任意分布的整数或浮点随机数生成。

一般来说,有几种方法可以解决此问题。有些时间是线性的,但是需要大的内存存储,有些时间是O(n log(n))时间。有些针对整数进行了优化,有些针对圆形直方图进行了定义(例如:在一天中生成随机时间点)。在上面提到的库中,我将本文用于整数情况,并将此配方用于浮点数。它(仍然)缺少圆形直方图支持,通常比较混乱,但是效果很好。


2

I had the same problem. Given a set where each item has a probability and whose items' probabilities sum up to one, I wanted to draw a sample efficiently, i.e. without sorting anything and without repeatedly iterating over the set.

The following function draws the lowest of N uniformly distributed random numbers within the interval [a,1). Let r be a random number from [0,1).

next(N,a)=1(1a)rN

You can use this function to draw an ascending series (ai) of N uniformly distributed random numbers in [0,1). Here is an example with N=10:

a0=next(10,0)
a1=next(9,a0)
a2=next(8,a1)

a9=next(1,a8)

While drawing that ascending series (ai) of uniformly distributed numbers, iterate over the set of probabilities P which represents your arbitraty (yet finite) distribution. Let 0k<|P| be the iterator and pkP. After drawing ai, increment k zero or more times until p0pk>ai. Then add pk to your sample and move on with drawing ai+1.


Example with the op's set {(1,0.04),(2,0.5),(3,0.46)} and sample size N=10:

i  a_i    k  Sum   Draw
0  0.031  0  0.04  1
1  0.200  1  0.54  2
2  0.236  1  0.54  2
3  0.402  1  0.54  2
4  0.488  1  0.54  2
5  0.589  2  1.0   3
6  0.625  2  1.0   3
7  0.638  2  1.0   3
8  0.738  2  1.0   3
9  0.942  2  1.0   3

Sample: (1,2,2,2,2,3,3,3,3,3)


If you wonder about the next function: It is the inverse of the probability that one of N uniformly distributed random numbers lies within the interval [a,x) with x1.


It appears the problem you are addressing abruptly changed in the second paragraph from one that samples from an arbitrary discrete distribution to sampling from a uniform distribution. Its solution appears not to be relevant to the question that was asked here.
whuber

I clarified the last part.
casi

Your answer still seems unrelated to the question. Could you perhaps provide a small but nontrivial worked example of your algorithm? Show us how it would generate a single draw from the set {1,2,3} according to the probabilities given in the question.
whuber

I added an example. My answer has something in common with David M Kaplan's answer (stats.stackexchange.com/a/26860/93386), but requires just one instead of N (= sample size) iterations over the set, at the expense of drawing N N-th roots. I profiled both procedures, and mine was much faster.
casi

Thank you for the clarification (+1). It may be of interest to many readers that this isn't a simple random sample, because the outcomes appear in a predetermined, fixed order: a random permutation would have to be applied to the results in order to create a simple random sample. You might also be interested in a parallelizable version of this algorithm in which
aj=i=1jlog(ui)i=1N+1log(ui)
where u1,,uN+1 is a simple random sample of Uniform(0,1] variates.
whuber
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.