Python中scipy/numpy的exp溢出问题?

27 投票
5 回答
102852 浏览
提问于 2025-04-16 08:04

以下错误是什么意思:

Warning: overflow encountered in exp

在使用Python的scipy/numpy时通常意味着什么?我在计算一个对数形式的比率,也就是log(a) + log(b),然后用exp取这个结果的指数,并使用logsumexp进行求和,具体如下:

c = log(a) + log(b)
c = c - logsumexp(c)

数组b中的一些值是故意设置为0的。它们的对数会是负无穷大(-Inf)。

这个警告可能是什么原因呢?谢谢。

5 个回答

4

我觉得你可以用这个方法来解决这个问题:

归一化

我通过这个方法解决了问题。在使用这个方法之前,我的分类准确率是86%。使用这个方法后,准确率提高到了96%!太棒了!
首先:
最小-最大缩放

最小-最大缩放

其次:
Z-score标准化

Z-score标准化

这些都是实现归一化的常见方法。
我使用了第一种方法,并对其进行了修改。最大值被除以10。 所以结果的最大值是10。这样exp(-10)就不会溢出了!
希望我的回答能帮到你!(^_^)

9

当你需要处理指数运算时,事情就变得复杂了,因为这个函数增长得非常快,容易出现下溢或上溢的情况。一个常见的例子是在统计学中,通常需要对不同幅度的指数进行求和。由于这些数字可能非常大或非常小,人们通常会取对数,以保持在一个“合理”的范围内,这就是所谓的对数域:

exp(-a) + exp(-b) -> log(exp(-a) + exp(-b))

不过,问题依然存在,因为exp(-a)仍然可能出现下溢。例如,exp(-1000)已经小到无法用双精度浮点数表示了。所以像这样:

log(exp(-1000) + exp(-1000))

会得到-无穷大(log(0 + 0)),尽管你手动计算时可能会预期得到-1000(-1000 + log(2))。而logsumexp这个函数做得更好,它会先找出一组数字中的最大值,然后把它从对数中提取出来:

log(exp(a) + exp(b)) = m + log(exp(a-m) + exp(b-m))

虽然它并不能完全避免下溢(比如当a和b差别很大时),但它能在最终结果中避免大部分精度问题。

32

在你的情况下,这意味着在你的数组中,b 的值在某个地方非常小,因此你计算出来的数字(a/bexp(log(a) - log(b)))可能会大到超出你用来存储结果的数组类型(比如 float32、float64 等)所能承受的范围。

Numpy 可以设置成:

  1. 忽略这些错误,
  2. 打印错误,但不发出警告来停止执行(这是默认设置),
  3. 记录错误,
  4. 发出警告,
  5. 抛出错误,
  6. 调用用户自定义的函数。

你可以查看 numpy.seterr 来控制它如何处理浮点数组中的下溢和上溢等问题。

撰写回答