Sigmoid 函数 returns 1 用于较大的正输入
Sigmoid function returns 1 for large positive inputs
我在 Python 中编写了以下函数来计算标量、向量或矩阵的 sigmoid 函数。
def sigmoid(z):
sig = 1.0/(1.0 + np.exp(-z))
return sig
对于相对较大的 z 正值,e^-z
return 是一个非常小的接近于零 (0) 的值,因此 sig 的值四舍五入为 1。我的最终 objective 是确定逻辑回归算法的成本函数。由于 sigmoid returns 恰好为 1,因此 log(1-1)
return 'nan'。我怎样才能以我的 sigmoid() 函数将 return 正确的值而不是将 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.]])
正如 jdehesa 已经提到的,您的问题与精度限制有关。你可以在这里阅读更多:
https://docs.python.org/2/tutorial/floatingpoint.html
您可以尝试使用避免四舍五入的小数 class:
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
但对于大多数情况,手动处理带有逻辑检查的小结果的建议可能是最好的。
我通过用 np.minimum
& np.maximum
:
包装 sigmoid 函数克服了这个问题
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% 的准确率。
我在 Python 中编写了以下函数来计算标量、向量或矩阵的 sigmoid 函数。
def sigmoid(z):
sig = 1.0/(1.0 + np.exp(-z))
return sig
对于相对较大的 z 正值,e^-z
return 是一个非常小的接近于零 (0) 的值,因此 sig 的值四舍五入为 1。我的最终 objective 是确定逻辑回归算法的成本函数。由于 sigmoid returns 恰好为 1,因此 log(1-1)
return 'nan'。我怎样才能以我的 sigmoid() 函数将 return 正确的值而不是将 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.]])
正如 jdehesa 已经提到的,您的问题与精度限制有关。你可以在这里阅读更多: https://docs.python.org/2/tutorial/floatingpoint.html
您可以尝试使用避免四舍五入的小数 class:
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
但对于大多数情况,手动处理带有逻辑检查的小结果的建议可能是最好的。
我通过用 np.minimum
& 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% 的准确率。