ITPub博客

首页 > > > 10678 如何准确计算 log(1 - exp(-x))

10678 如何准确计算 log(1 - exp(-x))

作者:格伯纳 时间:2017-07-22 08:26:14 0 删除 编辑

  今天正在写的机器学习代码里遇到了这样一个函数:f(x) = \log (1 - \exp(-x))。要怎么计算呢?

  咦?直接算不行吗?不行。计算机的精度是有限的。这个函数的定义域是 (0, +\infty)。当 x 十分接近 0 时,\exp(-x) 就十分接近 1,再用 1 去减它就会损失精度。当 x 特别大时,\exp(-x) 就接近 0,用 1 减它就得到 1,再取对数就完全变成 0 了。

  怎么办呢?原来,在许多编程语言中,提供了 log1p 和 expm1 两个函数。它们的功能是计算 g(x) = \log(1+x) 和 h(x) = \exp(x) - 1。若分步计算这两个式子,当 x 接近 0 时就会损失精度,而 log1p 和 expm1 两个函数则改用泰勒展开法间接计算这两个式子,在 x 接近 0 时仍能保持足够的精度。

  上面两个函数的泰勒展开分别为:g(x) = x - \frac{x^2}{2} + \frac{x^3}{3} - \ldots,h(x) = x + \frac{x^2}{2!} + \frac{x^3}{3!} + \ldots。当 x 很小时,取 2 ~ 3 项就够了。若只取一项也可以看出来,其实 g(x) 和 h(x) 在原点附近都是约等于 x 的。

  再回头看文章开头的函数 f(x)。当 x 很小时,我们可以借助 expm1 函数避免精度损失:f(x) = \log(-\mathrm{expm1}(-x))。当 x 很大时,可以借助 log1p 函数避免精度损失: f(x) = \mathrm{log1p}(-\exp(-x))。由此也可以看出,f(x) 这个函数在x \rightarrow 0^+时近似为y = \log x,在x \rightarrow +\infty时近似为y = -\exp(-x)。

  那么多大的 x 算「很大」,多小算「很小」呢?文献 [1] 提出,可以用 \log 2 作为分界点,x<\log2 时就使用 expm1 函数,x>\log2 时就使用 log1p 函数。实验发现,这个分界点是最优的 —— 正好左侧用 expm1 函数计算误差小,右侧用 log1p 函数计算误差小。其实,f(x) 的图像是关于直线 y=-x 对称的,\log 2 正是图像与对称轴交点的横坐标。

参考文献:

[1] cran.r-project.org/web/

原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
管理员

注册时间:2018-03-30

  • 博文量
    2383
  • 访问量
    983857