machine-learning - 验证错误没有改变但训练损失减少的可能原因是什么?
问题描述
我使用预训练的 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没有变化,我不知道为什么,也许有人知道潜在的原因是什么?我已经阅读了一些博客,并检查了我的数据集,我确信我的数据集被正确分割。
解决方案
似乎您的模型无法推广到 val 集。这意味着模型无法找到(anchor,positive)与(anchor,negative)之间的差异。在这种情况下,(anchor, positive) 的距离 - (anchor,negative) 的距离 ~= 0。并且由于您的边距设置为 1。损失将保持在 1。回忆一下TripletMarginLoss中的损失函数定义。
我建议sigmoid
从最后一层删除激活,并替换relu
为LeakyRelu
以提高模型的稳健性。
推荐阅读
- react-native - 从数组映射时如何调用onChangeText函数
- json - 网络响应中相同 json 对象的不同键类型
- swift - 将 selectionRects(for:) 与 UITextField 子类一起使用
- java - MIUI 10.2 Redmi 设备的锁屏上未设置壁纸
- javascript - 如何对一个集合中多个文档的值求和并将总和推送到另一个集合中的文档
- c# - Couchbase 错误 System.InvalidOperationException:此流不支持超时
- c# - 选择 linq 列表很慢
- sql - 如何仅替换 Oracle 中文本的某些部分?
- javascript - 在 React Native Button 中未定义 this.props.navigation.navigate('Form')
- javascript - 在显示 SweetAlert2 Toastr mixin 之前等待所有 ajax 调用结束