对数中的灾难性取消

计算科学 浮点 稳定 数字
2021-12-06 22:02:25

我正在尝试以低相对误差的双精度浮点实现以下函数:

logsum(x,y)=log(exp(x)+exp(y))

这在统计应用程序中广泛使用,以添加在对数空间中表示的概率或概率密度。当然,都可能容易上溢或下溢,这很糟糕,因为日志空间首先用于避免下溢。这是典型的解决方案:exp(x)exp(y)

logsum(x,y)=x+log1p(exp(yx))

取消确实发生了,但被减轻了。更糟糕的是当接近时。这是一个相对误差图:yxexpxlog1p(exp(yx))

在此处输入图像描述

处被截断,以强调曲线的形状,在该曲线上发生取消。我已经看到高达的错误,并怀疑它会变得更糟。(FWIW,“ground truth”函数是使用 MPFR 的 128 位精度的任意精度浮点数实现的。)1014logsum(x,y)=01011

我尝试了其他的重新配方,结果都是一样的。使用作为外部表达式,通过取一个接近 1 的值的日志会发生同样的错误。使用作为外部表达式,取消发生在内部表达式中。loglog1p

现在,绝对误差很小,所以exp(logsum(x,y))具有非常小的相对误差(在一个 epsilon 内)。有人可能会争辩说,因为logsum对概率(不是对数概率)真的很感兴趣,这个可怕的相对错误不是问题。它可能通常不是,但我正在编写一个库函数,我希望它的客户能够指望相对误差不比舍入误差差多少。

看来我需要一种新方法。可能是什么?

1个回答

公式

logsum(x,y)=max(x,y)+log1p(exp(abs(xy))
应该是数值稳定的。它推广到
logiexi=ξ+logiexiξ,   ξ=maxixi

如果对数和非常接近于零并且您想要较高的相对精度,您可以使用 \mathrm{logsum}(x,y)=\max(x,y)+\mathrm{ lexp(即,超过双精度) 几乎是线性的

logsum(x,y)=max(x,y)+lexp(xy)
lexp(z):=log(1+e|z|)
z