标签归档:sigmoid

如何在Python中计算逻辑Sigmoid函数?

问题:如何在Python中计算逻辑Sigmoid函数?

这是逻辑S形函数:

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

假设x = 0.458。

F(x)=?

This is a logistic sigmoid function:

I know x. How can I calculate F(x) in Python now?

Let’s say x = 0.458.

F(x) = ?


回答 0

应该这样做:

import math

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

现在,您可以通过调用以下命令进行测试:

>>> sigmoid(0.458)
0.61253961344091512

更新:请注意,以上内容主要旨在将给定表达式直接一对一转换为Python代码。它没有经过测试或已知是数字上正确的实现。如果您知道您需要一个非常强大的实现,那么我相信其他人实际上已经对此问题进行了一些思考。

This should do it:

import math

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

And now you can test it by calling:

>>> sigmoid(0.458)
0.61253961344091512

Update: Note that the above was mainly intended as a straight one-to-one translation of the given expression into Python code. It is not tested or known to be a numerically sound implementation. If you know you need a very robust implementation, I’m sure there are others where people have actually given this problem some thought.


回答 1

它也可以在scipy中使用:http ://docs.scipy.org/doc/scipy/reference/produced/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

正如预期的那样logistic.cdf(比)慢expit。当用单个值调用时,它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.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 /

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

It is also available in 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

which is only a costly wrapper (because it allows you to scale and translate the logistic function) of another scipy function:

In [3]: from scipy.special import expit

In [4]: expit(0.458)
Out[4]: 0.61253961344091512

If you are concerned about performances continue reading, otherwise just use expit.

Some benchmarking:

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

As expected logistic.cdf is (much) slower than expit. expit is still slower than the python sigmoid function when called with a single value because it is a universal function written in C ( http://docs.scipy.org/doc/numpy/reference/ufuncs.html ) and thus has a call overhead. This overhead is bigger than the computation speedup of expit given by its compiled nature when called with a single value. But it becomes negligible when it comes to big arrays:

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))
   ....: 

(You’ll notice the tiny change from math.exp to np.exp (the first one does not support arrays, but is much faster if you have only one value to compute))

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

But when you really need performance, a common practice is to have a precomputed table of the the sigmoid function that hold in RAM, and trade some precision and memory for some speed (for example: http://radimrehurek.com/2013/09/word2vec-in-python-part-two-optimizing/ )

Also, note that expit implementation is numerically stable since version 0.14.0: https://github.com/scipy/scipy/issues/3385


回答 2

这里是你将如何实现在数字上稳定的方式物流乙状结肠(如描述这里):

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

通常,多项式逻辑乙状结肠为:

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可能更准确。)

Here’s how you would implement the logistic sigmoid in a numerically stable way (as described here):

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)

Or perhaps this is more accurate:

import numpy as np

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

Internally, it implements the same condition as above, but then uses log1p.

In general, the multinomial logistic sigmoid is:

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)))

(However, logaddexp.reduce could be more accurate.)


回答 3

其他方式

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

another way

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

回答 4

通过转换tanh函数的另一种方式:

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

Another way by transforming the tanh function:

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

回答 5

我觉得许多人可能对更改S型函数的自由参数感兴趣。其次,对于许多应用程序,您想使用镜像的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*(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)

I feel many might be interested in free parameters to alter the shape of the sigmoid function. Second for many applications you want to use a mirrored sigmoid function. Third you might want to do a simple normalization for example the output values are between 0 and 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

And to draw and compare:

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

Finally:

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


回答 6

使用numpy包允许您的Sigmoid函数解析向量。

根据深度学习,我使用以下代码:

import numpy as np
def sigmoid(x):
    s = 1/(1+np.exp(-x))
    return s

Use the numpy package to allow your sigmoid function to parse vectors.

In conformity with Deeplearning, I use the following code:

import numpy as np
def sigmoid(x):
    s = 1/(1+np.exp(-x))
    return s

回答 7

来自@unwind的好答案。但是,它不能处理极端的负数(引发OverflowError)。

我的进步:

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

Good answer from @unwind. It however can’t handle extreme negative number (throwing OverflowError).

My improvement:

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

回答 8

Tensorflow还包含一个sigmoid功能:https : //www.tensorflow.org/versions/r1.2/api_docs/python/tf/sigmoid

import tensorflow as tf

sess = tf.InteractiveSession()
x = 0.458
y = tf.sigmoid(x)

u = y.eval()
print(u)
# 0.6125396

Tensorflow includes also a sigmoid function: https://www.tensorflow.org/versions/r1.2/api_docs/python/tf/sigmoid

import tensorflow as tf

sess = tf.InteractiveSession()
x = 0.458
y = tf.sigmoid(x)

u = y.eval()
print(u)
# 0.6125396

回答 9

Logistic Sigmoid函数的数字稳定版本。

    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)

A numerically stable version of the logistic sigmoid function.

    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)

回答 10

一班

In[1]: import numpy as np

In[2]: sigmoid=lambda x: 1 / (1 + np.exp(-x))

In[3]: sigmoid(3)
Out[3]: 0.9525741268224334

A one liner…

In[1]: import numpy as np

In[2]: sigmoid=lambda x: 1 / (1 + np.exp(-x))

In[3]: sigmoid(3)
Out[3]: 0.9525741268224334

回答 11

使用pandas DataFrame/Series或时的向量化方法numpy array

最佳答案是针对单点计算的优化方法,但是当您要将这些方法应用于pandas系列或numpy数组时,它需要require apply,这基本上是在后台循环的方法,它将遍历每行并应用该方法。这是相当低效的。

为了加快我们的代码,我们可以使用向量化和numpy广播:

x = np.arange(-5,5)
np.divide(1, 1+np.exp(-x))

0    0.006693
1    0.017986
2    0.047426
3    0.119203
4    0.268941
5    0.500000
6    0.731059
7    0.880797
8    0.952574
9    0.982014
dtype: float64

或搭配pandas Series

x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))

Vectorized method when using pandas DataFrame/Series or numpy array:

The top answers are optimized methods for single point calculation, but when you want to apply these methods to a pandas series or numpy array, it requires apply, which is basically for loop in the background and will iterate over every row and apply the method. This is quite inefficient.

To speed up our code, we can make use of vectorization and numpy broadcasting:

x = np.arange(-5,5)
np.divide(1, 1+np.exp(-x))

0    0.006693
1    0.017986
2    0.047426
3    0.119203
4    0.268941
5    0.500000
6    0.731059
7    0.880797
8    0.952574
9    0.982014
dtype: float64

Or with a pandas Series:

x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))

回答 12

您可以将其计算为:

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))

you can calculate it as :

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

or conceptual, deeper and without any imports:

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

or you can use numpy for matrices:

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

回答 13

import numpy as np

def sigmoid(x):
    s = 1 / (1 + np.exp(-x))
    return s

result = sigmoid(0.467)
print(result)

上面的代码是python中的逻辑Sigmoid函数。如果我知道x = 0.467,则S型函数F(x) = 0.385。您可以尝试替换上面代码中已知的x的任何值,您将获得的其他值F(x)

import numpy as np

def sigmoid(x):
    s = 1 / (1 + np.exp(-x))
    return s

result = sigmoid(0.467)
print(result)

The above code is the logistic sigmoid function in python. If I know that x = 0.467 , The sigmoid function, F(x) = 0.385. You can try to substitute any value of x you know in the above code, and you will get a different value of F(x).