如何在Python中计算logistic sigmoid函数?

这是一个logistic sigmoid函数:

在这里输入图像说明

我知道x。 我现在如何计算Python中的F(x)?

假设x = 0.458。

F(x)=?

这应该做到这一点:

import math def sigmoid(x): return 1 / (1 + math.exp(-x)) 

现在你可以通过调用以下方法来testing它:

 >>> sigmoid(0.458) 0.61253961344091512 

更新 :请注意,上面的主要目的是将给定的expression式直接一对一地转换为Python代码。 它没有经过testing或已知是数字声音的实现。 如果你知道你需要一个非常强大的实现,我相信也有其他人在其中实际上已经给这个问题一些想法。

这也是在scipy: http ://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.logistic.html

 In [1]: from scipy.stats import logistic In [2]: logistic.cdf(0.458) Out[2]: 0.61253961344091512 

这只是一个昂贵的包装(因为它允许您扩展和翻译后勤function)的另一个scipyfunction:

 In [3]: from scipy.special import expit In [4]: expit(0.458) Out[4]: 0.61253961344091512 

如果您担心表演继续阅读,否则只需使用expit

一些基准:

 In [5]: def sigmoid(x): ....: return 1 / (1 + math.exp(-x)) ....: In [6]: %timeit -r 1 sigmoid(0.458) 1000000 loops, best of 1: 371 ns per loop In [7]: %timeit -r 1 logistic.cdf(0.458) 10000 loops, best of 1: 72.2 µs per loop In [8]: %timeit -r 1 expit(0.458) 100000 loops, best of 1: 2.98 µs per loop 

正如所料, logistic.cdfexpit要慢很多。 当用单个值调用时, expit仍然比python sigmoid函数慢,因为它是用C语言编写的通用函数( http://docs.scipy.org/doc/numpy/reference/ufuncs.html ),因此有一个调用高架。 当用单个值调用时,这个开销大于由其编译特性给出的expit的计算加速。 但是当涉及大数组时,它变得微不足道:

 In [9]: import numpy as np In [10]: x = np.random.random(1000000) In [11]: def sigmoid_array(x): ....: return 1 / (1 + np.exp(-x)) ....: 

(你会注意到从math.expnp.exp的细微变化(第一个不支持数组,但是如果你只有一个值计算,速度会快得多))

 In [12]: %timeit -r 1 -n 100 sigmoid_array(x) 100 loops, best of 1: 34.3 ms per loop In [13]: %timeit -r 1 -n 100 expit(x) 100 loops, best of 1: 31 ms per loop 

但是,当你真的需要性能的时候,一个普通的做法是在sigmoid函数中保存一个预先计算好的表,并且在某些速度下交换一些精度和内存(例如: http : //radimrehurek.com/2013/09 / word2vec-in-python-part-two-optimize / )

另外请注意,从版本0.14.0开始, expit实现在数值上是稳定的: https : //github.com/scipy/scipy/issues/3385

以下是如何以数字稳定的方式实现Logistic S形(如下所述):

 def sigmoid(x): "Numerically-stable sigmoid function." if x >= 0: z = exp(-x) return 1 / (1 + z) else: z = exp(x) return z / (1 + z) 

或者这可能更准确:

 import numpy as np def sigmoid(x): return math.exp(-np.logaddexp(0, -x)) 

在内部,它实现与上面相同的条件,但是使用log1p

一般来说,多项Logistic S形是:

 def nat_to_exp(q): max_q = max(0.0, np.max(q)) rebased_q = q - max_q return np.exp(rebased_q - np.logaddexp(-max_q, np.logaddexp.reduce(rebased_q))) 

(但是, logaddexp.reduce可能更准确。)

其他方式

 >>> def sigmoid(x): ... return 1 /(1+(math.e**-x)) ... >>> sigmoid(0.458) 

来自@unwind的好回答。 但是它不能处理极端的负数(抛出OverflowError)。

我的改进:

 def sigmoid(x): try: res = 1 / (1 + math.exp(-x)) except OverflowError: res = 0.0 return res 

我觉得很多人可能会对自由参数感兴趣来改变sigmoid函数的形状。 其次,对于许多应用程序,您希望使用镜像S形函数。 第三,你可能想做一个简单的规范化,例如输出值在0和1之间。

尝试:

 def normalized_sigmoid_fkt(a, b, x): ''' Returns array of a horizontal mirrored normalized sigmoid function output between 0 and 1 Function parameters a = center; b = width ''' s= 1/(1+np.exp(b*(xa))) return 1*(s-min(s))/(max(s)-min(s)) # normalize function to 0-1 

并画出和比较:

 def draw_function_on_2x2_grid(x): fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2) plt.subplots_adjust(wspace=.5) plt.subplots_adjust(hspace=.5) ax1.plot(x, normalized_sigmoid_fkt( .5, 18, x)) ax1.set_title('1') ax2.plot(x, normalized_sigmoid_fkt(0.518, 10.549, x)) ax2.set_title('2') ax3.plot(x, normalized_sigmoid_fkt( .7, 11, x)) ax3.set_title('3') ax4.plot(x, normalized_sigmoid_fkt( .2, 14, x)) ax4.set_title('4') plt.suptitle('Different normalized (sigmoid) function',size=10 ) return fig 

最后:

 x = np.linspace(0,1,100) Travel_function = draw_function_on_2x2_grid(x) 

乙状结肠功能图

通过变换tanh函数的另一种方法是:

 sigmoid = lambda x: .5 * (math.tanh(.5 * x) + 1)