【问题标题】:PyTorch Multi Class Classification using CrossEntropyLoss - not converging使用 CrossEntropyLoss 的 PyTorch 多类分类 - 不收敛
【发布时间】:2020-10-20 23:07:33
【问题描述】:

我正在尝试建立一个简单的网络来输出一个数字属于三个类别之一的概率。这些是小于 1.1、介于 1.1 和 1.5 之间以及大于 1.5。我正在使用类别标签为 0、1 和 2 的交叉熵损失,但无法解决问题。

每次训练时,网络都会输出第 2 类的最大概率,而不管输入如何。我似乎能够达到的最低损失是 0.9ish。任何关于我哪里出错的建议将不胜感激!所有代码如下。

class gating_net(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(gating_net, self).__init__()
        self.linear1 = nn.Linear(input_dim, 32)
        self.linear2 = nn.Linear(32, output_dim)

    def forward(self, x):
        # The original input (action) is used as the residual.
        x = F.relu(self.linear1(x))
        x = F.sigmoid(self.linear2(x))
        return x

learning_rate = 0.01
batch_size = 64
epochs = 500
test = 1

gating_network = gating_net(1,3)

optimizer = torch.optim.SGD(gating_network.parameters(), lr=learning_rate, momentum=0.9)
scheduler = ReduceLROnPlateau(optimizer, mode='max', factor=0.5, patience=20, verbose=True)

for epoch in range (epochs):
    input_ = []
    label_ = []

    for i in range (batch_size):
        scale = random.randint(10,20)/10

        input = scale
        if scale < 1.1:
            label = np.array([0])
        elif 1.1 < scale < 1.5:
            label = np.array([1])
        else:
            label = np.array([2])

        input_.append(np.array([input]))
        label_.append(label)

    optimizer.zero_grad()

    # get output from the model, given the inputs
    output = gating_network.forward(torch.FloatTensor(input_))
    old_label  = torch.FloatTensor(label_)

    # get loss for the predicted output
    loss = nn.CrossEntropyLoss()(output, old_label.squeeze().long())

    # get gradients w.r.t to parameters
    loss.backward()
    # update parameters
    optimizer.step()
    scheduler.step(loss)

    print('epoch {}, loss {}'.format(epoch, loss.item()))

    if loss.item() < 0.01:
        print("########## Solved! ##########")
        torch.save(mod_network.state_dict(), './supervised_learning/run_{}.pth'.format(test))
        break

    # save every 500 episodes
    if epoch % 100 == 0:
        torch.save(gating_network.state_dict(), './run_{}.pth'.format(test))

【问题讨论】:

    标签: pytorch classification cross-entropy


    【解决方案1】:
    • 您的代码在每个 epoch 生成训练数据(在本例中也是每个批次)。这是非常多余的,但这并不意味着代码不起作用。然而,确实影响训练的一件事是类之间训练数据的不平衡。使用您的代码,大部分训练数据始终标记为2。如此直观地,您的网络将始终了解有关2 类的更多信息。这就是为什么在非常小的 500 时期,网络将所有类别分类为2,因为这是一种快速简便的降低损失的方法。然而,当网络不能通过应用关于标签2 的知识来降低损失时,它也会学习到10。因此可以训练网络,尽管效率不高。
    • 继续上一期,使用ReduceLROnPlateau 也效率不高,因为在网络开始学习标签01 时,学习率已经很小(直观地说)。并不意味着它无法训练,但可能需要很长时间。
    • CrossEntropyLoss 在内部计算 LogSoftmax,因此在网络末端有 Sigmoid 意味着您在 Sigmoid 层之后有一个 Softmax 层,这可能不是您想要的。我认为网络不一定是“错误的”,但训练起来会更加困难。
    • 实际上缩放1.1 被标记为2,因为你有&lt;1.1&gt;1.1

    TL;DR

    摆脱sigmoidscheduler。 我能够在大约 15000 个 epoch 的某个地方获得 Solved!(学习率和批量大小与您的代码相同)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-11
      • 2016-11-19
      • 1970-01-01
      • 2020-01-08
      • 2018-08-18
      • 2018-06-17
      • 2022-01-06
      • 2012-01-07
      相关资源
      最近更新 更多