NetLogo计算beta分发/功能

时间:2015-09-18 17:35:43

标签: netlogo

我正在使用NetLogo中的统计信息扩展来计算beta函数:

set z (stats:beta (H + 1) (T + 1))

其中H和T是硬币翻转中的头部和尾部的数量。 使用统计信息扩展并不重要,使用beta函数的阶乘表达式时遇到同样的问题。

问题是,当H + T > 168时,NetLogo会报告z = 0并且有一些我无法执行的程序[特别是beta发布]

有没有办法在Netlogo中近似beta函数(或分布),以免它遇到这个问题?

非常感谢!

3 个答案:

答案 0 :(得分:2)

我终于设法解决了我自己的问题。我希望这对其他人也有帮助。 主要问题是计算大型因子 - 正如评论中提到的那样。特别是171!简直太计算了。因此,最佳解决方案是最大限度地减少计算此类数字的需要。

对于离散情况,beta函数如下:

B(alpha,beta)=(alpha - 1)!(beta - 1)! /(alpha + beta - 1)!

错误是试图计算第一个提名者,然后是分母,然后分裂;因为分母太大了。我找到了两个解决方案,其中一个比另一个好,但更复杂 - 但实际上我觉得它接近最优。

不太理想但更短的是基于使用最大的提名者简化分母的想法:

to-report betafunc [alpha beta]
  ifelse (alpha >= beta)
  [let v1 (factorial (beta - 1) (0))
   let v2 (factorial (alpha + beta - 1) (alpha - 1))
   report (v1 / v2)]
  [let v1 (factorial (alpha - 1) (0))
   let v2 (factorial (alpha + beta - 1) (beta - 1))
  report (v1 / v2)]
end

其中

to-report factorial [n m]
 if (n = m) [report 1]
 report (n * factorial (n - 1) (m))
end

这个问题是分母仍然快速增长。第二种解决方案的想法是通过简化阶乘的每一步来进行。

例如,如果我们有(5!8!)/(12)!我们可以把它表达为产品 (5.8 / 12)。(4.7 / 11)。(3.6 / 10)......(1.4 / 8)。(1.3 / 7)......(1.1 / 5)(1.1 / 4)......(1.1 / 1)

通过逐步简化序列的每个术语,我们确保事物不会那么快地成长。这是我的解决方案:

to-report stepwisefactorial3 [n1 n2 d]
  if (n1 = 0) [report stepwisefactorial2 (n2) (d)]
  if (n2 = 0) [report stepwisefactorial2 (n1) (d)]
  if (d = 0)  [report (stepwisefactorial1 (n1) * stepwisefactorial1 (n2))]
  report ((((n1 * n2) / d)) * stepwisefactorial3 (n1 - 1) (n2 - 1) (d - 1))
end

to-report stepwisefactorial2 [n d]
  if (n = 0) [report (1 / (stepwisefactorial1 (d)))]
  if (d = 0) [report stepwisefactorial1 (n)]
  report ((n / d)* stepwisefactorial2 (n - 1) (d - 1))
end

to-report stepwisefactorial1 [d]
  if d = 0 [ report 1 ]
  report d * stepwisefactorial1 (d - 1)
end

如果alpha + beta>仍然会爆炸。 345;但这是进步。

我希望这有帮助!

答案 1 :(得分:2)

根据Chris的回答,统计信息扩展确实有一个Gamma函数的日志, stats:loggamma 。它处理的参数大大超过171,因此a和b也可以增加到172以上。

observer> show stats:beta 85 86
observer: 1.2864854397253604E-52
observer> show exp (stats:loggamma 85 + stats:loggamma 86 - stats:loggamma (85 + 86))
observer: 1.2864854397251408E-52
observer> show stats:beta 86 86
observer: 0
observer> show exp (stats:loggamma 86 + stats:loggamma 86 - stats:loggamma (86 + 86))
observer: 6.394810665301235E-53
observer> show exp (stats:loggamma 200 + stats:loggamma 200 - stats:loggamma (200 + 200))
observer: 9.713217247613997E-122

已发布新版本的统计信息扩展程序(v1.4.0),其中包含使用日志的“bigBeta”功能。

答案 2 :(得分:1)

(这是一个侧面评论,但无论如何,这个问题已经得到了回答。)

我想知道如何使用日志。

Beta(x,y) = Gamma(x) * Gamma(y) / Gamma(x + y)
= exp ( ln(Gamma(x)) + ln(Gamma(y)) - ln(Gamma(x + y)) )

稍微玩一下就会发现Stats扩展程序非常智能,可以通过这种方式计算Beta,而真正归结的是Gamma中的溢出

observer> show stats:gamma 171
observer: 7.257415615308E306
observer> show stats:gamma 172
observer: Infinity

(我在这里唠叨 http://www.stata.com/support/faqs/statistics/calculating-beta-function/。)