Python中和的日志的数字函数

时间:2011-09-20 06:29:42

标签: python logarithm numerical-computing

鉴于log(a)log(b),我想计算log(a+b)(以数字稳定的方式)。

我为此写了一个小函数:

def log_add(logA,logB):
    if logA == log(0):
        return logB
    if logA<logB:
        return log_add(logB,logA)
    return log( 1 + math.exp(logB-logA) ) + logA

我编写了一个程序,其中到目前为止是最耗时的代码。显然我可以尝试优化它(例如,消除递归调用)。

您是否了解mathnumpy计算log(a+b)的标准log(a)log(b)函数?

如果没有,你知道为这个函数制作单个C ++钩子的简单方法吗?它不是一个复杂的函数(它使用浮点数),正如我所说,它占据了我运行时的大部分时间。

先谢谢,数字方法忍者!

2 个答案:

答案 0 :(得分:9)

注意:到目前为止,最好的答案是使用numpy.logaddexp(logA,logB)

为什么要与log(0)进行比较?这等于-numpy.inf,在这种情况下,您来到log(1 + math.exp(-inf-logB) ) + logB,这会将自身缩减为logB。此调用始终会发出一条极其缓慢的警告消息。

我可以想出这个单行。但是,你需要真正测量,看看这实际上是否更快。它只使用一个“复杂”计算函数而不是你使用的两个,并且没有发生递归,if仍然存在,但在fabs / {{1}中隐藏(并且可能已经优化) }}

maximum

编辑:

我做了一个快速的timeit(),结果如下:

  1. 您的原始版本耗时约120秒
  2. 我的版本花了大约30秒
  3. 我从您的版本中删除了与log(0)的比较,结果为20秒
  4. 我编辑了我的代码以保留def log_add(logA,logB): return numpy.logaddexp(0,-numpy.fabs(logB-logA)) + numpy.maximum(logA,logB) ,但如果它已经下降到18秒,那么它也适用于你的递归。
  5. 更新了代码,您也可以使用内联更新公式切换递归调用,但这对我的时序测试没什么影响:

    logaddexp

    编辑2:

    正如pv在评论中指出的那样,实际上你可以def log_add2(logA, logB): if logA < logB: return log_add2(logB, logA) return numpy.logaddexp(0,logB-logA)+logA 来计算numpy.logaddexp(logA, logB),这当然等于log(exp(logA)+exp(logB))。我计时(在上面的同一台机器上),它进一步下降到大约10秒。所以我们已经下降到大约1/12,不差;)。

答案 1 :(得分:-1)

def log_add(logA, logB): 
    return math.log(math.exp(logA) + math.exp(logB))

太慢了?还是不准确?

相关问题