pytorch 是不是在 nn.Linear 中自动应用 softmax

Posted

技术标签:

【中文标题】pytorch 是不是在 nn.Linear 中自动应用 softmax【英文标题】:Does pytorch apply softmax automatically in nn.Linearpytorch 是否在 nn.Linear 中自动应用 softmax 【发布时间】:2019-12-22 06:29:06 【问题描述】:

pytorch 中定义了一个分类网络模型,

class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # hidden layer
        self.out = torch.nn.Linear(n_hidden, n_output)   # output layer

    def forward(self, x):
        x = F.relu(self.hidden(x))      # activation function for hidden layer
        x = self.out(x)
        return x

这里是否应用了softmax?在我的理解中,事情应该是这样的,

class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden, n_output):
        super(Net, self).__init__()
        self.hidden = torch.nn.Linear(n_feature, n_hidden)   # hidden layer
        self.relu =  torch.nn.ReLu(inplace=True)
        self.out = torch.nn.Linear(n_hidden, n_output)   # output layer
        self.softmax = torch.nn.Softmax(dim=n_output)
    def forward(self, x):
        x = self.hidden(x)      # activation function for hidden layer
        x = self.relu(x)
        x = self.out(x)
        x = self.softmax(x)
        return x

我知道F.relu(self.relu(x))也是在应用relu,但是第一块代码没有应用softmax,对吧?

【问题讨论】:

是的,linear 不会自动应用 softmax。 @unlut 谢谢,你觉得第二段代码合适吗? 在我看来是正确的。 在相关说明中,如果您使用的是nn.CrossEntropyLoss,则应用 log-softmax,然后是 nll-loss。您可能想确保您没有两次应用 softmax,因为 softmax not idempotent. @jodag 谢谢!!!我在@dennlinger 的回答下还有其他问题。希望也能听到您的建议! 【参考方案1】:

了解 @jodag 在他的评论中已经说过的话,并稍微扩展一下以形成完整的答案:

,PyTorch 不会自动应用 softmax,您可以随时根据需要应用 torch.nn.Softmax()但是,softmax 有some issues with numerical stability,我们希望尽可能避免。一种解决方案是使用 log-softmax,但这往往比直接计算要慢。

特别是当我们使用负对数似然作为损失函数时(在 PyTorch 中,这是 torch.nn.NLLLoss,我们可以利用 (log-)softmax+NLLL 的导数实际上是 mathematically quite nice 和简单的事实,即这就是为什么将两者组合成一个函数/元素是有意义的。然后结果是torch.nn.CrossEntropyLoss。再次注意,这仅直接适用于网络的最后一层,任何其他计算都不会受到任何影响.

【讨论】:

如果我理解正确的话,最好将nn.CrossEntropyLoss作为损失函数应用于最后一层nn.Linear()的输出,而不是直接使用nn.Softmax()。对吗? 还有一个问题,nn.Softmax()的输出可以认为是某个类的概率,而nn.Linear()的所有输出之和不保证等于1。失去了最终输出的意义? 回答你的第一条评论:你并没有真正用损失函数替换任何层,而是用不同的损失替换你当前的损失函数(应该是nn.NLLLoss),同时删除最后nn.Softmax()。不过,我认为您的想法已经是正确的。第二个问题:由于您的损失函数仍然“应用” log softmax(或者至少您的导数基于此),因此解释仍然成立。如果您以任何其他方式使用输出,例如在推理期间,您当然必须在这种情况下重新应用 softmax。

以上是关于pytorch 是不是在 nn.Linear 中自动应用 softmax的主要内容,如果未能解决你的问题,请参考以下文章

pytorch nn.Linear()详解

pytorch中的神经网络子模块(线性模块)——torch.nn.Linear

pytorch之求梯度和nn.Linear的理解

如何在 Pytorch 的“nn.Sequential”中展平输入

PyTorch nn.Linear layer output nan 在格式良好的输入和权重上

关于对PyTorch中nn.Linear的官方API文档解读