Python的numpy.exp函数中的溢出错误

Fco*_*der 5 python numpy scipy

我想这样使用numpy.exp:

cc = np.array([
    [0.120,0.34,-1234.1]
])

print 1/(1+np.exp(-cc))
Run Code Online (Sandbox Code Playgroud)

但这给了我错误:

/usr/local/lib/python2.7/site-packages/ipykernel/__main__.py:5: RuntimeWarning: overflow encountered in exp
Run Code Online (Sandbox Code Playgroud)

我不明白为什么?我怎样才能解决这个问题?似乎问题在于第三个数字(-1234.1)

Pra*_*een 11

正如fuglede所说,这里的问题是np.float64无法处理的数字那么大exp(1234.1).请尝试使用np.float128:

>>> cc = np.array([[0.120,0.34,-1234.1]], dtype=np.float128)
>>> cc
array([[ 0.12,  0.34, -1234.1]], dtype=float128)
>>> 1 / (1 + np.exp(-cc))
array([[ 0.52996405,  0.58419052,  1.0893812e-536]], dtype=float128)
Run Code Online (Sandbox Code Playgroud)

但请注意,使用扩展精度存在某些怪癖.它可能无法在Windows上运行; 你实际上并没有获得完整的128位精度; 当数字通过纯python时你可能会失去精度.您可以在此处详细了解详细信息.

对于大多数实际用途,您可能接近于1 / (1 + <a large number>)零.也就是说,只需忽略警告并继续前进.Numpy会为您提供近似值(使用时np.float64):

>>> 1 / (1 + np.exp(-cc))
/usr/local/bin/ipython3:1: RuntimeWarning: overflow encountered in exp
  #!/usr/local/bin/python3.4
array([[ 0.52996405,  0.58419052,  0.        ]])
Run Code Online (Sandbox Code Playgroud)

如果你想抑制警告,你可以scipy.special.expit按照WarrenWeckesser的建议使用评论:

>>> from scipy.special import expit
>>> expit(cc)
array([[ 0.52996405,  0.58419052,  0.        ]])
Run Code Online (Sandbox Code Playgroud)


fug*_*ede 6

numpyfloat 表示的最大值是1.7976931348623157e + 308,其对数约为709.782,因此无法表示np.exp(1234.1).

In [1]: import numpy as np

In [2]: np.finfo('d').max
Out[2]: 1.7976931348623157e+308

In [3]: np.log(_)
Out[3]: 709.78271289338397

In [4]: np.exp(709)
Out[4]: 8.2184074615549724e+307

In [5]: np.exp(710)
/usr/local/bin/ipython:1: RuntimeWarning: overflow encountered in exp
  #!/usr/local/bin/python3.5
Out[5]: inf
Run Code Online (Sandbox Code Playgroud)


jmd*_*_dk 6

一个可能的解决方案是使用该decimal模块,它允许您使用任意精度的浮点数。numpy下面是一个使用 100 位精度的浮点数组的示例:

import numpy as np
import decimal

# Precision to use
decimal.getcontext().prec = 100

# Original array
cc = np.array(
    [0.120,0.34,-1234.1]
)
# Fails
print(1/(1 + np.exp(-cc)))    

# New array with the specified precision
ccd = np.asarray([decimal.Decimal(el) for el in cc], dtype=object)
# Works!
print(1/(1 + np.exp(-ccd)))
Run Code Online (Sandbox Code Playgroud)

  • 你确实失去了很多速度。实际上,“numpy”将整个计算委托给“Decimal”对象,这些操作无法由 CPU 本地执行。对于大型阵列,时间差异会很严重。 (2认同)