当我使用torch.sigmoid
时,我的模型可以工作。我试图通过创建一个新的sigmoid函数来使sigmoid变得更陡峭:
def sigmoid(x):
return 1 / (1 + torch.exp(-1e5*x))
但是由于某种原因,渐变并没有流过它(我得到的是NaN
)。我的函数是否有问题,或者有没有办法简单地将PyTorch实现更改为更陡峭(像我的函数一样)?
代码示例:
def sigmoid(x):
return 1 / (1 + torch.exp(-1e5*x))
a = torch.tensor(0.0, requires_grad=True)
b = torch.tensor(0.58, requires_grad=True)
c = sigmoid(a-b)
c.backward()
a.grad
>>> tensor(nan)
发布于 2021-04-22 06:22:00
问题似乎是,当sigmoid实现的输入为负时,torch.exp
的参数会变得非常大,从而导致溢出。使用torch.autograd.set_detect_anomaly(True)
作为建议的here,您可以看到以下错误:
RuntimeError: Function 'ExpBackward' returned nan values in its 0th output.
如果您确实需要使用您定义的函数,一种可能的解决方法是对参数进行条件检查(但我不确定它是否稳定,因此我无法评论它的有用性):
def sigmoid(x):
if x >= 0:
return 1./(1+torch.exp(-1e5*x))
else:
return torch.exp(1e5*x)/(1+torch.exp(1e5*x))
在这里,else分支中的表达式通过将分子和分母乘以torch.exp(1e5*x)
等同于原始函数。这可确保torch.exp
的参数始终为负或接近于零。
正如trialNerror所指出的,指数值是如此之高,以至于除了非常接近于零的值之外,其他任何地方的渐变都将计算为零,因为实际的斜率将非常小,并且无法通过数据类型来解析。因此,如果你计划在网络中使用它,你可能会发现很难学习任何东西,因为梯度几乎总是为零。根据您的用例,选择一个较小的指数可能会更好。
发布于 2021-04-22 06:08:25
你在你的指数中加上1e5的扩张值。1e5的指数是如此之高,以至于在这里没有希望得到有意义的结果。您可能会得到一个NaN,因为您正试图通过一个计算图进行反向传播,该图在某一时刻的计算结果为inf
(甚至更高!)
总之,要使函数的斜率更陡峭,记住df(a.x)/dx = a.df(x)/dx
,所以你需要将它的参数乘以一个大于1的值(并且不是负的,你将改变你的导数的符号),但不要那么大!尝试使用10个可能,它还取决于您将在函数中输入的输入的数量级
https://stackoverflow.com/questions/67203664
复制相似问题