对于较大的正输入,S型函数返回1

时间:2018-09-20 10:36:35

标签: python machine-learning logistic-regression sigmoid

我在Python中编写了以下函数,以计算标量,向量或矩阵的S型函数。

def sigmoid(z):
    sig = 1.0/(1.0 + np.exp(-z))
    return sig

对于z较大的正值,e^-z返回一个非常小的值,接近零(0),因此sig的值四舍五入为1。我的最终目标是确定逻辑回归算法的成本函数。由于sigmoid恰好返回1,所以log(1-1)返回'nan'。我该如何解决该问题,使我的sigmoid()函数将返回正确的值,而不将e^-z舍入为0?

当我使用均值和标准差对输入特征进行归一化时,它工作正常。但是有办法使它与更大的z值一起工作吗?

此外,我在Matlab上尝试了同样的方法,并且无需进行标准化也可以正常工作。

>>> Z = np.array([[60, 100],[20, 80]])
>>> Z
array([[ 60, 100],
       [ 20,  80]])
>>> np.exp(-Z)
array([[8.75651076e-27, 3.72007598e-44],
       [2.06115362e-09, 1.80485139e-35]])
>>> 1.0/(1.0 + np.exp(-Z))
array([[1., 1.],
       [1., 1.]])

2 个答案:

答案 0 :(得分:1)

jdehesa已经提到,您的问题是精度限制。你可以在这里阅读更多: https://docs.python.org/2/tutorial/floatingpoint.html

您可以尝试使用避免舍入的Decimal类:

from decimal import Decimal
import numpy as np
import math

def sigmoid(z):
    sig = Decimal(1.0)/(Decimal(1.0) + Decimal(np.exp(-z)))
    return sig


math.log(Decimal(1)-sigmoid(60))
>>> -59.97257293350302

,但这只会工作到一定程度(我发现它已经失败了80次)。我做了一些阅读,如果您确实需要更高的精度,则可以通过将以下值从默认值28增加来更改Decimal对象的精度:

from decimal import *
getcontext().prec = 28 

此处有更多详细信息:

https://docs.python.org/2/library/decimal.html

在大多数情况下,建议使用逻辑检查手动处理较小的结果可能是最好的。

答案 1 :(得分:1)

我通过用np.minimumnp.maximum包装S型函数来克服了这个问题:

def sigmoid(x):
    sig = 1 / (1 + np.exp(-x))     # Define sigmoid function
    sig = np.minimum(sig, 0.9999)  # Set upper bound
    sig = np.maximum(sig, 0.0001)  # Set lower bound
    return sig

结果我的损失开始像这样

this

但是培训损失和测试损失都可以很好地收敛,我使用逻辑回归在一个很小的数据集上获得了约90%的准确度。