5

我在 Python 中编写了以下函数来计算标量、向量或矩阵的 sigmoid 函数。

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.]])
4

2 回答 2

4

我通过用np.minimum&包装 sigmoid 函数克服了这个问题np.maximum

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

结果我的损失开始看起来像这样

这个

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

于 2019-03-26T18:55:11.443 回答
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

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

于 2018-09-20T11:20:16.210 回答