首页 > 解决方案 > 验证错误没有改变但训练损失减少的可能原因是什么?

问题描述

我使用预训练的 ResNet 为每张图像提取 1000 维特征,然后将这些图像放入我自建的网络中进行分类任务并使用三元组损失函数。

我的代码有一部分:

class Network(torch.nn.Module):
    def __init__(self,n_feature = 1000, n_hidden_1 = 200, n_hidden_2 = 100, n_hidden_3 = 50, n_hidden_4 = 20,n_output = 3):
        super(Network, self).__init__()
        self.net = torch.nn.Sequential(    
                        torch.nn.Linear(n_feature, n_hidden_1),
                        torch.nn.BatchNorm1d(n_hidden_1),
                        torch.nn.ReLU(),
                        torch.nn.Linear(n_hidden_1, n_hidden_2),
                        torch.nn.BatchNorm1d(n_hidden_2),
                        torch.nn.ReLU(),
                        torch.nn.Linear(n_hidden_2, n_hidden_3),
                        torch.nn.BatchNorm1d(n_hidden_3),
                        torch.nn.ReLU(),
                        torch.nn.Linear(n_hidden_3, n_hidden_4),
                        torch.nn.BatchNorm1d(n_hidden_4),
                        torch.nn.ReLU(),
                        torch.nn.Linear(n_hidden_4, n_output),
                        torch.nn.Sigmoid()
                                )
    def forward(self, x):
        x = self.net(x)
        return x

并且有训练和验证过程:

    for epoch in tqdm(range(n_epoch)):
        model.train()
        for step, (batch_anchor, batch_positive, batch_negative )in enumerate(train_loader):

            anchor_out = model(batch_anchor)
            positive_out = model(batch_positive)
            negative_out = model(batch_negative)

            loss = loss_func(anchor_out, positive_out, negative_out)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

        model.eval()
        for step, (batch_anchor_val, batch_positive_val, batch_negative_val) in enumerate(val_loader):

            anchor_out_val = model(batch_anchor_val)
            positive_out_val = model(batch_positive_val)
            negative_out_val = model(batch_negative_val)

            loss_val = loss_func(anchor_out_val, positive_out_val, negative_out_val)

我在其中定义损失函数和优化器,如下所示:

optimizer = optim.Adam(model.parameters(), lr=0.002)
loss_func = torch.nn.TripletMarginLoss(p=2, margin=1)

和一些结果:

Epoch: 1/50 - Loss: 0.8764 - Val_loss: 0.9920
Epoch: 2/50 - Loss: 0.7035 - Val_loss: 0.9897
Epoch: 3/50 - Loss: 0.6313 - Val_loss: 0.9972
Epoch: 4/50 - Loss: 0.5958 - Val_loss: 0.9980
Epoch: 5/50 - Loss: 0.5724 - Val_loss: 0.9930
Epoch: 6/50 - Loss: 0.5541 - Val_loss: 1.0123
...

训练时,train loss总是减少,但是val loss没有变化,我不知道为什么,也许有人知道潜在的原因是什么?我已经阅读了一些博客,并检查了我的数据集,我确信我的数据集被正确分割。

标签: machine-learningdeep-learningneural-networkpytorch

解决方案


似乎您的模型无法推广到 val 集。这意味着模型无法找到(anchor,positive)与(anchor,negative)之间的差异。在这种情况下,(anchor, positive) 的距离 - (anchor,negative) 的距离 ~= 0。并且由于您的边距设置为 1。损失将保持在 1回忆一下TripletMarginLoss中的损失函数定义。

我建议sigmoid从最后一层删除激活,并替换reluLeakyRelu以提高模型的稳健性。


推荐阅读