【问题标题】:Equal output values given for Multiclass Classification为多类分类给出相等的输出值
【发布时间】:2019-02-24 15:06:23
【问题描述】:

我正在尝试使用 PyTorch 构建一个用于预测图像中手指数量的 CNN。网络:

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()

        self.Layer1 = nn.Sequential(
        nn.Conv2d(in_channels=3, out_channels=16, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=(2, 2)),
        nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=128, out_channels=256, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=(2, 2)),
        nn.Conv2d(in_channels=256, out_channels=16, kernel_size=(1, 1)),
        nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=128, out_channels=256, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=(2, 2)),
        nn.Conv2d(in_channels=256, out_channels=16, kernel_size=(1, 1)),
        nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=(2, 2)),
        nn.Conv2d(in_channels=128, out_channels=16, kernel_size=(1, 1)),
        nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.MaxPool2d(kernel_size=(2, 2)),
        nn.Conv2d(in_channels=128, out_channels=16, kernel_size=(1, 1)),
        nn.Conv2d(in_channels=16, out_channels=32, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=32, out_channels=64, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=64, out_channels=128, kernel_size=(3, 3)),
        nn.ReLU(),
        nn.Conv2d(in_channels=128, out_channels=256, kernel_size=(3, 3)),
        nn.ReLU(),
        )

        self.Layer2 = nn.Sequential(
        nn.Linear(1536, 100),
        nn.Tanh(),
        nn.Linear(100, 6),
        nn.Softmax()
        )
        self.optimizer = optimizers.Adadelta(self.parameters())

    def forward(self, X):
        X = self.Layer1(X)
        print(X.shape)
        X = self.Layer2(X.reshape(1, 1536))
        X = X.squeeze()

        return X

    def calc_loss(self, X, num):
        out = self.forward(X).unsqueeze(dim=0)
        print("Output: "+str(out))
        target = torch.tensor([num], dtype=torch.int64).cuda()
        criterion = nn.CrossEntropyLoss()
        loss = criterion(out, target)
        return loss

    def train_step(self, X, Y):
        loss = self.calc_loss(X, Y)
        print(loss)
        self.optimizer.zero_grad()
        loss.backward()
        self.optimizer.step()

但是,训练完成后,所有预测的值几乎相同(大约 0.15 ~ 0.18)。

看起来好像网络平均了输出概率以最小化损失,而不是学习实际值。

无论我将 Softmax 用于具有交叉熵损失的最后一层,还是使用具有二元交叉熵、MSE 或 SmoothL1Loss 的 Sigmoid,我都会得到相同的结果。

如果使用 Adam 优化器,我会得到类似的结果,只是在 1e-12 ~ 1e-14 的范围内。

我错过了什么?

【问题讨论】:

  • 说实话,你的实现有点混乱,为什么不把模型实现和训练循环分开呢?这将使您的调试更加容易
  • 我想将所有网络操作与数据操作分开。所有数据都从不同的文件加载并从该文件馈送到模型。
  • train_step 在循环中多次调用上述注释中提到的文件的不同 X 和 Y 值。
  • 我明白了。您是否尝试在单个批次上过度拟合您的模型?只是为了测试,以确保一切正常?
  • 好的,我再次查看了您的问题,对于 CrossEntropyLoss,您需要不带 Softmax 的原始输出。

标签: python deep-learning computer-vision conv-neural-network pytorch


【解决方案1】:

如果您使用CrossEntropyLoss,则无需在forward 中使用Softmax。它已经包含在CrossEntropyLoss 中,因此您需要“原始”输出。但是,如果您在推理期间需要 Softmax,请改用 NLLLoss + 'Softmax'。

您可以找到更多信息here

【讨论】:

  • 哦,我不知道。谢谢!
  • 欢迎您!对不起,我从第一眼就没有注意到它。我的坏)
猜你喜欢
  • 1970-01-01
  • 2017-03-26
  • 2017-06-12
  • 2021-05-22
  • 2017-12-28
  • 2020-10-25
  • 2014-06-20
  • 2019-11-27
  • 1970-01-01
相关资源
最近更新 更多