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

zqdjd7g9  于 2022-11-23  发布在  Python
关注(0)|答案(5)|浏览(129)

我想这样使用numpy.exp

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

print 1/(1+np.exp(-cc))

但这给了我错误:

/usr/local/lib/python2.7/site-packages/ipykernel/__main__.py:5: RuntimeWarning: overflow encountered in exp

我不明白为什么?我该怎么解决这个问题?问题似乎是第三个数字(-1234.1)

csbfibhn

csbfibhn1#

正如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)

但是请注意,使用扩展精度有一些怪癖,它可能在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.        ]])

如果您想隐藏警告,可以使用scipy.special.expit,如WarrenWeckesser在问题的注解中所建议的:

>>> from scipy.special import expit
>>> expit(cc)
array([[ 0.52996405,  0.58419052,  0.        ]])
vshtjzan

vshtjzan2#

numpy浮点数可表示的最大值是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
mtb9vblg

mtb9vblg3#

一个可能的解决方案是使用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)))
ulydmbyx

ulydmbyx4#

exp(-1234.1)对于32位或64位浮点数太小。由于无法表示,numpy将生成正确的警告。
使用IEEE 754 32bit floating-point数,它可以表示的最小正数是2^(-149),大约是1 e-45。
如果你使用IEEE 754 64 bit floating-point数,最小的正数是2^(-1074),大约是1 e-327。
在这两种情况下,它都不能表示像exp(-1234.1)这样小的数,exp(-1234.1)大约为1 e-535。
你应该使用scipy中的expit函数来计算sigmoid函数,这样可以提高精度。
实际上,exp(-1234.1)是一个非常小的数字。如果在您的用例中舍入到零是有意义的,numpy通过将其舍入到零产生良性结果。

hfwmuf9z

hfwmuf9z5#

如果不关心精度,可以使用numpy.clip
float64中:

cc = np.clip(cc, -709.78, 709.78)

float32中:

cc = np.clip(cc, -88.72, 88.72)

相关问题