我应该在交叉熵之前应用softmax吗?

时间:2019-03-06 18:49:59

标签: pytorch cross-entropy

pytorch教程(https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py)在CIFAR数据集上训练卷积神经网络(CNN)。

    class Net(nn.Module):
        def __init__(self):
            super(Net, self).__init__()
            self.conv1 = nn.Conv2d(3, 6, 5)
            self.pool = nn.MaxPool2d(2, 2)
            self.conv2 = nn.Conv2d(6, 16, 5)
            self.fc1 = nn.Linear(16 * 5 * 5, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)

        def forward(self, x):
            x = self.pool(F.relu(self.conv1(x)))
            x = self.pool(F.relu(self.conv2(x)))
            x = x.view(-1, 16 * 5 * 5)
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x 

除了最后一层fc3,该网络看起来不错,它可以预测在没有softmax的情况下属于10个类别的概率。在计算交叉熵损失之前,我们不应该先应用softmax来确保fc层的输出在0和1之间并且是和吗?

我通过应用softmax并重新运行进行了测试,但是准确度下降到了35%左右。这似乎违反直觉。有什么解释?

1 个答案:

答案 0 :(得分:0)

PyTorch中的CrossEntropyLoss已通过Softmax实现:

https://pytorch.org/docs/stable/nn.html#torch.nn.CrossEntropyLoss

  

此标准将nn.LogSoftmax()和nn.NLLLoss()合并到一个类中。

编辑: 答案的第二部分的答案要复杂一些。精度降低可能有多种原因。从理论上讲,由于您添加的softmax层可以合理的精度预测正确的答案,因此下一层应该能够通过保留最后两层之间具有相同性的最大值来做到这一点。尽管softmax再次规范了有界输出(介于0和1之间),但它可能会改变它们的分配方式,但仍可以保留最大值并因此保留所预测的类。

但是,实际上,情况有所不同。当输出层中有double softmax时,基本上可以通过更改输出函数的方式来改变输出到网络的梯度。具有交叉熵的softmax是首选的损耗函数,因为它会产生梯度。您可以通过计算成本函数的梯度来自己证明这一点,并考虑到每个“激活”(softmax)都介于0和1之间的事实。“原始”函数背后的另一个softmax只是将梯度与值相乘。介于0和1之间,从而减小该值。这会影响权重的更新。也许可以通过更改学习率来固定它,但是强烈建议不要这样做。只要拥有一个softmax就可以了。
有关更深入的解释,请参见Michael Nielsen's book, chapter 3