在scipy.special.expit
中,逻辑函数的实现方式如下:
if x < 0
a = exp(x)
a / (1 + a)
else
1 / (1 + exp(-x))
但是,我已经看到其他语言/框架中的实现只是做
1 / (1 + exp(-x))
我想知道scipy版本实际带来了多少好处。
对于非常小的x
,结果接近0.即使exp(-x)
溢出到Inf
,它也能正常工作。
答案 0 :(得分:7)
这实际上只是为了稳定 - 投入非常大的数值可能会带来意想不到的结果。
如果expit
与1 / (1 + exp(-x))
一样实施,那么将-710
的值放入函数会返回nan
,而-709
会给出一个值关闭如预期的那样为零。这是因为exp(710)
太大而不能成为双倍。
代码中的分支只意味着避免了这种情况。
另请参阅Stack Overflow上的this question and answer。
答案 1 :(得分:4)
似乎使用效率更高:
if x < -709
sigmoid = 0.0
else
sigmoid = 1.0 / (1.0 + exp(-x))
除非您需要10 ^ -309精度的数字(见下文),这似乎有点过分!
>>> 1 / (1 + math.exp(709.78))
5.5777796105262746e-309
答案 2 :(得分:0)
另一种方法是
python
np.where(x > 0, 1. / (1. + np.exp(-x)), np.exp(x) / (np.exp(x) + np.exp(0)))
由于np.exp(x) / (np.exp(x) + np.exp(0))
相当于1. / (1. + np.exp(-x))
,但对于负值更稳定