如何将 PyTorch sigmoid 函数更改为更陡峭

How to change PyTorch sigmoid function to be steeper

我的模型在我使用 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)

你在你的指数中放了 1e5 的扩张。 1e5 的指数高得令人难以置信,因此没有希望在这里获得有意义的结果。您可能得到一个 NaN,因为您正试图通过一个计算图反向传播,该计算图在某个时候被评估为 inf(甚至超过!)

无论如何,要使函数的斜率更陡,请记住 df(a.x)/dx = a.df(x)/dx 因此您需要将其参数乘以大于 1 的值(而不是负数,您将更改导数的符号) ,但没有那么大!也许尝试 10,它还取决于您要放入函数中的输入的数量级

问题似乎是当您的 sigmoid 实现的输入为负时,torch.exp 的参数变得非常大,导致溢出。按照here的建议使用torch.autograd.set_detect_anomaly(True),可以看到错误:

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 所指出的那样,指数值非常高,除了非常接近于零的值外,您的梯度在其他任何地方都将计算为零,因为实际斜率将非常小并且无法通过以下方式解决数据类型。因此,如果您打算在网络中使用它,您可能会发现学习任何东西都非常困难,因为梯度几乎总是零。 select 较小的指数可能更好,具体取决于您的用例。