我正在使用NetLogo中的统计信息扩展来计算beta函数:
set z (stats:beta (H + 1) (T + 1))
其中H和T是硬币翻转中的头部和尾部的数量。 使用统计信息扩展并不重要,使用beta函数的阶乘表达式时遇到同样的问题。
问题是,当H + T > 168
时,NetLogo会报告z = 0
并且有一些我无法执行的程序[特别是beta发布]
有没有办法在Netlogo中近似beta函数(或分布),以免它遇到这个问题?
非常感谢!
答案 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/。)