pytorch
教程(tutorial.html#sphx-glr-beginner-blitz-cifar10-tutorial-py)在CIFAR数据集上训练卷积神经网络。
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
,它预测的概率属于10个类别,没有一个软最大值。在计算交叉熵损失之前,我们不应该先应用softmax来确保fc层的输出介于0到1和和之间吗?
我通过应用softmax和重新运行来测试这一点,但是准确度下降到了35%左右。这似乎有违直觉。原因是什么?
发布于 2019-03-06 10:54:15
CrossEntropyLoss in PyTorch已经用Softmax实现了:
https://pytorch.org/docs/stable/nn.html#torch.nn.CrossEntropyLoss
这个标准将nn.LogSoftmax()和nn.NLLLoss()组合在一个类中。
你问题的第二部分的答案要复杂一些。精确度下降的原因可能有多种。从理论上讲,由于您添加的softmax层能够以合理的精度预测正确的答案,下面的层应该能够通过保留后两层之间的最大值来实现同样的操作。虽然softmax再次规范了这些有界输出(介于0到1之间),但它可能会改变这些输出的分布方式,但仍然可以保留最大值,从而保留预测的类。
然而,在实践中,情况有点不同。当输出层中有双softmax时,基本上会改变输出函数,使其改变传播到网络的梯度。具有交叉熵的softmax是一个优选的损失函数,因为它产生的梯度。你可以通过计算成本函数的梯度来证明这一点,并解释了每个“激活”( softmax )都有界于0到1之间的事实。原始函数后面的附加softmax只是将梯度乘以0到1之间,从而降低了值。这会影响权重的更新。也许可以通过改变学习速率来解决这个问题,但这并不是很好的建议。只要有一个软盘,你就完蛋了。
有关这方面的更深刻解释,请参见迈克尔·尼尔森的书,第三章。
https://stackoverflow.com/questions/55030217
复制