如何在Python中计算逻辑S形函数?
这是逻辑S形函数:如何在Python中计算逻辑S形函数?,python,sigmoid,Python,Sigmoid,这是逻辑S形函数: In [3]: from scipy.special import expit In [4]: expit(0.458) Out[4]: 0.61253961344091512 我知道x。现在如何在Python中计算F(x) 假设x=0.458 F(x)=?这应该可以做到: import math def sigmoid(x): return 1 / (1 + math.exp(-x)) 现在您可以通过调用以下命令进行测试: >>> sigmo
In [3]: from scipy.special import expit
In [4]: expit(0.458)
Out[4]: 0.61253961344091512
我知道x。现在如何在Python中计算F(x)
假设x=0.458
F(x)=?这应该可以做到:
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
现在您可以通过调用以下命令进行测试:
>>> sigmoid(0.458)
0.61253961344091512
更新:请注意,上述内容主要是将给定表达式直接一对一地转换为Python代码。它未经测试,也未被认为是数字上可靠的实现。如果您知道您需要一个非常健壮的实现,我相信还有其他人确实考虑过这个问题。另一种方法
>>> def sigmoid(x):
... return 1 /(1+(math.e**-x))
...
>>> sigmoid(0.458)
它也可以在scipy中获得: 这只是另一个scipy函数的昂贵包装(因为它允许您扩展和转换逻辑函数):
In [3]: from scipy.special import expit
In [4]: expit(0.458)
Out[4]: 0.61253961344091512
如果您关心性能,请继续阅读,否则请使用。
一些基准:
正如预期的那样,logistic.cdf
比expit
慢(很多)expit
在使用单个值调用时仍然比pythonsigmoid
函数慢,因为它是用C()编写的通用函数,因此具有调用开销。当使用单个值调用时,此开销大于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
的微小变化(第一个不支持数组,但如果您只需要计算一个值,则速度要快得多))
但当您确实需要性能时,通常的做法是在RAM中保存一个sigmoid函数的预计算表,并用一些精度和内存换取一些速度(例如:)
另外,请注意,
expit
自0.14.0版以来,实现在数值上是稳定的:以下是如何以数值稳定的方式实现逻辑s形图(如所述):
或许这更准确:
import numpy as np
def sigmoid(x):
return np.exp(-np.logaddexp(0, -x))
在内部,它实现与上面相同的条件,但随后使用log1p
一般来说,多项式逻辑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)))
来自@unwind的回答很好。然而,它不能处理极端负数(抛出溢出错误) 我的进步:
def sigmoid(x):
try:
res = 1 / (1 + math.exp(-x))
except OverflowError:
res = 0.0
return res
转换
tanh
函数的另一种方法:
sigmoid = lambda x: .5 * (math.tanh(.5 * x) + 1)
我觉得很多人可能对改变sigmoid函数形状的自由参数感兴趣。其次,对于许多应用程序,您希望使用镜像的sigmoid函数。第三,您可能需要进行简单的规范化,例如,输出值介于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)
Tensorflow还包括一个
sigmoid
功能:
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)
def sigmoid(x):
位置掩码=(x>=0)
负屏蔽=(x<0)
z=np.类零(x,dtype=float)
z[pos\u mask]=np.exp(-x[pos\u mask])
z[neg_mask]=np.exp(x[neg_mask])
top=np.one_like(x,dtype=float)
顶部[neg_mask]=z[neg_mask]
返回顶部/(1+z)
使用numpy包允许您的sigmoid函数解析向量
根据Deeplearning,我使用以下代码:
import numpy as np
def sigmoid(x):
s = 1/(1+np.exp(-x))
return s
一行
In[1]: import numpy as np
In[2]: sigmoid=lambda x: 1 / (1 + np.exp(-x))
In[3]: sigmoid(3)
Out[3]: 0.9525741268224334
上面的代码是python中的logistic sigmoid函数。
如果我知道x=0.467
,
S形函数,F(x)=0.385
。您可以尝试替换上述代码中已知的任何x值,当使用pandas DataFrame/Series
或numpy array
时,您将获得不同的F(x)
矢量化方法:
最重要的答案是针对单点计算的优化方法,但当您想将这些方法应用于pandas系列或numpy阵列时,它需要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
或使用熊猫系列:
x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))
您可以将其计算为:
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))
下面是执行相同操作的python函数
def sigmoid(x) :
return 1.0/(1+np.exp(-x))
此功能和展开功能之间有什么区别?math.e**-x比math.exp(-x)好吗?在输出结果方面没有区别。如果您想知道速度方面的差异,可以使用timeit来计时它们的执行时间。但这并不重要。
pow
通常是根据exp
和log
实现的,因此直接使用exp
几乎肯定会更好。当x
非常负时,会出现溢出。因为我经常需要它来尝试一些小事情:sigmoid=lambda x:1/(1+math.exp(-x))
这不适用于x的极端负值。我一直在使用这个不幸的实现,直到我注意到它正在创建NAN。如果将math.exp
替换为np.exp
,则不会得到NAN,尽管会得到运行时警告。将math.exp
与numpy数组一起使用可能会产生一些错误,例如:TypeError:只有长度为1的数组才能转换为Python标量。为了避免这种情况,您应该使用numpy.exp
。只需在表达式之前添加x=max(-709,x)
就可以减轻数值不稳定性吗?这样更好,但您仍然会遇到负值的数值冲击问题。使用浮点(1.)而不是整数(1)在你的sigmoid函数中,你可以减少10%的运行时间。我不确定我是否理解你的意思(示例中使用了浮点),但在任何情况下,很少计算整数上的sigmoid。kd88的意思是,你在函数(1)中使用的数字文字被解析为整数,
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
x = pd.Series(np.arange(-5,5))
np.divide(1, 1+np.exp(-x))
import math
def sigmoid(x):
return 1 / (1 + math.exp(-x))
def sigmoid(x):
return 1 / (1 + 2.718281828 ** -x)
import numpy as np #make sure numpy is already installed
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid(x) :
return 1.0/(1+np.exp(-x))