Python 中求和对数的数值函数
给定 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
我编写了一个程序,这是迄今为止最耗时的代码段。显然我可以尝试优化它(例如消除递归调用)。
您知道用于从 log(a)
log(a+b) 的标准 math
或 numpy
函数吗> 和log(b)
?
如果没有,您是否知道为该函数创建单个 C++ 挂钩的简单方法?这不是一个复杂的函数(它使用浮点数),正如我所说,它占用了我的大部分运行时间。
预先感谢数值方法忍者!
Given log(a)
and log(b)
, I want to compute log(a+b)
(in a numerically stable way).
I wrote a little function for this:
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
I wrote a program where this is by far the most time-consuming piece of code. Obviously I could try to optimize it (eliminate the recursive call, for instance).
Do you know of a standard math
or numpy
function for computing log(a+b)
from log(a)
and log(b)
?
If not, do you know of a simple way to make a single C++ hook for this function? It's not a complicated function (it uses floats), and as I said, it's taking up the majority of my runtime.
Thanks in advance, numerical methods ninja!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
注意:到目前为止,最好的答案是简单地使用 numpy.logaddexp(logA,logB)。
为什么要与
log(0)
进行比较?这等于-numpy.inf
,在这种情况下,您会得到log(1 + math.exp(-inf-logB) ) + logB
,它会将自身简化为 logB 。这个调用总是会给出一个警告消息,速度非常慢。我可以想出这样一句话。然而,您需要真正测量一下,看看这是否真的更快。它只使用一个“复杂”计算函数,而不是您使用的两个,并且没有发生递归,
if
仍然存在,但隐藏(并且可能优化)在fabs/<代码>最大值。
编辑:
我做了一个快速 timeit() ,结果如下:
更新代码,您还可以使用内联更新公式切换递归调用,但这在我的计时测试中几乎没有什么区别:
编辑2:
正如评论中的 pv 所指出的,您实际上可以只执行
numpy.logaddexp(logA, logB)
归结为计算log(exp(logA)+exp(logB))
,它当然等于log(A+B)
。我对它进行了计时(在与上面相同的机器上),它进一步下降到大约 10 秒。所以我们已经降到了 1/12 左右,还不错;)。Note: Best answer until now is to simply use
numpy.logaddexp(logA,logB)
.Why exactly do you compare with
log(0)
? This is equal to-numpy.inf
, in this case you come tolog(1 + math.exp(-inf-logB) ) + logB
Which reduces itself to logB. This call always will give an warning message which is extremely slow.I could come up with this one-liner. However you'll need to really measure to see if this is actually faster. It does only use one 'complex' calculation function instead of the two that you use, and no recursion is happening, the
if
is still there but hidden (and maybe optimized) infabs
/maximum
.edit:
I did a quick timeit() with following results :
logaddexp
but also worked with your recursive if and it went down to 18s.Updated code, you could also switch the recursive call with an inline updated formula but this made little difference in my timing tests:
Edit 2:
As pv noted in comments, you could actually just do
numpy.logaddexp(logA, logB)
which comes down to calculatinglog(exp(logA)+exp(logB))
which is of course equal tolog(A+B)
. I timed it (on the same machine as above) and it went further down to about 10s. So we've come down to about 1/12, not bad ;).是不是太慢了?还是不准确?
is too slow? or inaccurate?