这是一个logistic sigmoid函数:

我知道x,现在如何用Python计算F(x) ?

设x = 0.458。

F(x) = ?


当前回答

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

Try:

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*(x-a)))
   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)

其他回答

@unwind的回答很好。然而,它不能处理极端负数(抛出OverflowError)。

我的改进:

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

可以计算为:

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

或概念性的,更深的,没有任何进口性的:

def sigmoid(x):
  return 1 / (1 + 2.718281828 ** -x)

或者你可以对矩阵使用numpy:

import numpy as np #make sure numpy is already installed
def sigmoid(x):
  return 1 / (1 + np.exp(-x))

它也可以在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

这只是另一个scipy函数的一个昂贵的包装器(因为它允许你缩放和转换逻辑函数):

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

如预期的后勤。CDF比出口慢得多。当使用单个值调用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))
   ....: 

(你会注意到数学上的微小变化。Exp到np。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

但是当你真的需要性能时,一种常见的做法是在RAM中保存一个预先计算的sigmoid函数表,并以一些精度和内存换取一些速度(例如:http://radimrehurek.com/2013/09/word2vec-in-python-part-two-optimizing/)

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

这应该做到:

import math

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

现在你可以通过调用:

>>> sigmoid(0.458)
0.61253961344091512

更新:请注意,上面的操作主要是将给定表达式直接一对一地转换为Python代码。它没有经过测试,也没有被认为是一个数字上可靠的实现。如果你知道你需要一个非常健壮的实现,我相信其他人已经考虑过这个问题了。

logistic s型函数的数值稳定版本。

    def sigmoid(x):
        pos_mask = (x >= 0)
        neg_mask = (x < 0)
        z = np.zeros_like(x,dtype=float)
        z[pos_mask] = np.exp(-x[pos_mask])
        z[neg_mask] = np.exp(x[neg_mask])
        top = np.ones_like(x,dtype=float)
        top[neg_mask] = z[neg_mask]
        return top / (1 + z)