這些函數已經存在於scipy中。 sigmoid函數可以用作scipy.special.expit
。
In [36]: from scipy.special import expit
比較expit
到矢量雙曲線函數:
In [38]: x = np.linspace(-6, 6, 1001)
In [39]: %timeit y = sigmoid(x)
100 loops, best of 3: 2.4 ms per loop
In [40]: %timeit y = expit(x)
10000 loops, best of 3: 20.6 µs per loop
expit
也比自己實施公式更快:
In [41]: %timeit y = 1.0/(1.0 + np.exp(-x))
10000 loops, best of 3: 27 µs per loop
物流配送的CDF是雙曲線函數。它可作爲scipy.stats.logistic
的cdf
方法提供,但cdf
最終會調用expit
,因此使用該方法沒有意義。可以使用pdf
方法來計算S形函數,或具有較少的開銷的_pdf
方法的衍生物,但「滾動自己的」更快:
In [44]: def sigmoid_grad(x):
....: ex = np.exp(-x)
....: y = ex/(1 + ex)**2
....: return y
時序(x具有長度1001):
In [45]: from scipy.stats import logistic
In [46]: %timeit y = logistic._pdf(x)
10000 loops, best of 3: 73.8 µs per loop
In [47]: %timeit y = sigmoid_grad(x)
10000 loops, best of 3: 29.7 µs per loop
如果您打算使用遠離尾部的值,請注意您的實現。指數函數可以很容易地溢出。 logistic._cdf
比我快實現sigmoid_grad
更穩健一點:
In [60]: sigmoid_grad(-500)
/home/warren/anaconda/bin/ipython:3: RuntimeWarning: overflow encountered in double_scalars
import sys
Out[60]: 0.0
In [61]: logistic._pdf(-500)
Out[61]: 7.1245764067412855e-218
使用sech**2
(1/cosh**2
)的實現比上述sigmoid_grad
慢一點:
In [101]: def sigmoid_grad_sech2(x):
.....: y = (0.5/np.cosh(0.5*x))**2
.....: return y
.....:
In [102]: %timeit y = sigmoid_grad_sech2(x)
10000 loops, best of 3: 34 µs per loop
但它更好地處理尾巴:
In [103]: sigmoid_grad_sech2(-500)
Out[103]: 7.1245764067412855e-218
In [104]: sigmoid_grad_sech2(500)
Out[104]: 7.1245764067412855e-218
注意,'1 /(1 + NP。 exp(-x))'已經接受numpy數組作爲輸入並且速度非常快(我的猜測是memoization根本沒有幫助)。通過使用'vectorize',你可以讓它慢得多,因爲它使用慢for循環來實現。 –
x的大小是多少? – M4rtini
@ M4rtini,各不相同,但我一直假設我的規則計算,x通常是長度爲100的向量。 –