2016-11-21 1126 views
3

我想用numpy.exp這樣的:在Python的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)

+1

對於S形函數的討論,見我的回答在http://stackoverflow.com/questions/21106134/numpy-pure性能緩存(TL; DR:Use ['scipy.special.expit']](https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.expit.html) ) –

回答

5

由於fuglede說,這裏的問題是,np.float64無法處理一些大如exp(1234.1)。嘗試使用代替:

>>> 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時,你可能會失去精度。你可以閱讀更多關於細節here

對於大多數實際用途,您可能大致將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.  ]]) 
5

的最大值表示的由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 
+0

順便說一句,'exp(1234.1)'等於'9.17952305220754e + 535'。 – ForceBru

2

可能的解決方案是使用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))) 
+0

使用小數點時,您是否喪失了矢量化操作的優勢?我猜想,因爲numpy必須把它當作一個對象,你可能會隱含地失去速度? – Praveen

+1

你的速度確實很慢。實際上,'numpy'將整個計算委託給'Decimal'對象,這些對象不能由CPU本地執行。對於大型陣列,時差會非常嚴重。 –