模拟概率


9

谁能告诉我如何模拟Bernoulli(ab),其中,a,bN,使用抛硬币(如多次,你需要)与P(H)=p

我当时在考虑使用拒绝采样,但无法确定。


1
这是最初来自课程或教科书的问题吗?如果是这样,请添加[self-study]标签并阅读其wiki。请注意,您无需在问题结尾处请求帮助-我们知道在此发布信息的每个人都希望得到帮助!
Silverfish

1
@Glen_b在这里某处(尽管我不记得在哪里)上有一篇很棒的文章,关于为什么没有“概率为偏向硬币”这样的事情p,但是我知道这只是您的问题的外围问题!
Silverfish

2
@dsaxton这个问题说“您需要的数量”;它是有限的,但概率为1,但不受限制(您可能会超过固定的抛掷次数),但在此基础上提出异议就像说“抛掷一个公平的硬币直到得到一个头”一样,作为生成几何的方法不可行(112随机数。
Glen_b-恢复莫妮卡

1
@AbracaDabra这是一堂课的练习吗?如果没有,它将如何发生?
Glen_b-恢复莫妮卡

1
@Glen_b:这不是我班上的练习。这只是在我的思路中发生的……:按照经典的概率,拿一个公平的硬币,当您增加掷出次数时,收敛到一半。因此,对于有偏见的人也必须如此……这意味着要使硬币收敛到特定的数字,您需要PH为该数字。现在我想,如果我们想产生一个数字,但是我们有一个硬币,而PH是另一个数字(已知或未知),该怎么办?#Heads#tailsP(H)P(H)
AbracaDabra '16

Answers:


8

因为有无数种解决方案,所以让我们找到一种有效的解决方案。

这个想法的背后是实现伯努利变量的标准方法:将统一随机变量与参数a / b比较。当U < a / b时,返回1 ; 否则,返回0Ua/bU<a/b10

我们可以将硬币用作统一的随机数生成器p。要在任意间隔[ x y 内均匀生成数字,请翻转硬币。前进时,在间隔的前p个部分中递归生成一个统一值X;当它是尾巴时,从最后一个1 - p递归生成XU[x,y)XpX1p间隔的一部分。在某些时候,目标间隔会变得如此之小,以至于您从中选择一个数字并不重要:这就是递归开始的方式。显然,此过程会生成均匀的变量(达到任何所需的精度),这很容易通过归纳法得到证明。

这个想法不是有效的,但却导致了一种有效的方法。 由于在每个阶段都要从给定的间隔绘制数字,所以为什么不首先检查是否需要绘制呢?如果目标值超出此间隔,则您已经知道随机值与目标之间的比较结果。 因此,该算法倾向于迅速终止。(这可以解释为问题中要求的拒绝抽样程序。)[x,y)

我们可以进一步优化该算法。 在任何阶段,我们实际上都有两个硬币可以使用:通过重新标记我们的硬币,我们可以将其制成正面为正面。因此,作为预计算,我们可以递归选择无论哪种重标记都会导致终止所需的翻转次数较少。 (此计算可能是一个昂贵的步骤。)1p

例如,使用的硬币直接模拟Bernoulli 0.01 变量效率不高:平均需要翻转近十次。但是,如果我们使用p = 1 - 0.0 = 0.1一枚硬币,然后在短短的两年翻转,我们将确保完成和翻转的预期数量仅仅是1.2p=0.9(0.01)p=10.0=0.11.2

这是详细信息。

将任何给定的半开区间划分为区间I=[x,y)

[x,y)=[x,x+(yx)p)[x+(yx)p,y)=s(I,H)s(I,T).

这定义了以半开间隔运行的两个变换s T s(,H)s(,T)

就术语而言,如果是一组实数,则让表达式I

t<I

意味着是一个下界< X为所有X 。类似地,> 是上界tIt<xxIt>ItI

。(事实上,它会使没有什么区别,如果牛逼是真实的,而不是理性的,我们只需要0 牛逼1)。a/b=tt0t1

这是产生具有所需伯努利参数的变量的算法:Z

  1. Ñ = 0 = [ 0 1 n=0In=I0=[0,1)

  2. {抛硬币,以产生X Ñ + 1。设置I n + 1 = S I nX n + 1 递增n。}(tIn)Xn+1In+1=S(In,Xn+1).n

  3. 如果然后设置Ž = 1。否则,将Z设置0t>In+1Z=1Z=0


实作

为了说明,这里是R作为函数的算法的实现draw。其参数为目标值和区间[ X ÿ ,最初[ 0 1 。它使用辅助函数实现s。尽管不需要,但它也跟踪抛硬币的次数。它返回随机变量,抛数和检查的最后间隔。t[x,y)[0,1)ss

s <- function(x, ab, p) {
  d <- diff(ab) * p
  if (x == 1) c(ab[1], ab[1] + d) else c(ab[1] + d, ab[2])
}
draw <- function(target, p) {
  between <- function(z, ab) prod(z - ab) <= 0
  ab <- c(0,1)
  n <- 0
  while(between(target, ab)) {
    n <- n+1; ab <- s(runif(1) < p, ab, p)
  }
  return(c(target > ab[2], n, ab))
}

作为其使用和其精度的试验的一个例子,走的情况下p = 0.9。让我们画10 000使用的算法,报告的平均值(和它的标准误差)值,并注明翻转使用的平均数。t=1/100p=0.910,000

target <- 0.01
p <- 0.9
set.seed(17)
sim <- replicate(1e4, draw(target, p))

(m <- mean(sim[1, ]))                           # The mean
(m - target) / (sd(sim[1, ]) / sqrt(ncol(sim))) # A Z-score to compare to `target`
mean(sim[2, ])                                  # Average number of flips

0.00950.010.51549.8861p0.00941.177


我不禁在答案中看到了该解决方案与解决方案2之间的相似之处。假设我使用一个无偏硬币(对有偏硬币问题来说PS确实很有趣的解决方案),并在以2为基数进行所有计算/比较,而在以10为基数进行所有计算/比较,您有什么想法?
Cam.Davidson.Pilon,2016年

1
@cam我认为您可能会被我的示例所迷惑:尽管它们在基数10中使用了不错的数字,但该构造与任何特定基数无关。
whuber

2
a/bpn(1p)m(n+mm)pn(1p)m

5

P(H)=pP(H)=1/2P(H)=1/2

Bernoulli(ab)

解决方案1

baaP(first coin is heads | a heads in b coins)=ab

解决方案2

Bernoulli(p)p0.1=0.0001100110011001100110011...base 2

0.p bin(p)

在Python中:

def simulate(p):
    binary_p = float_to_binary(p)
    binary_string = '0.'
    index = 3
    while True:
        binary_string += '0' if random.random() < 0.5 else '1'
        if binary_string != binary_p[:index]:
            return binary_string < binary_p[:index]
        index += 1

一些证明:

np.mean([simulate(0.4) for i in range(10000)])

大约是0.4(但是不快)


好的答案,但是您能用方法1解释非理性p的方法吗?
AbracaDabra '16

2
p

p(0,1)(1,0)p(1p)1/2

4

我看到了一个简单的解决方案,但是毫无疑问,有很多方法可以做到这一点,大概有些方法比这更简单。该方法可以分为两个步骤:

  1. pHTH=(H,T)T=(T,H)

  2. a(ba)aa+(ba)=ab

    (这里需要进行一些计算以显示它,但是您可以通过处理递归关系来相当容易地找出这些概率……或者可以通过对无限序列求和来实现……或者还有其他方法。)

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.