PyTorch 模型未收敛

Posted

技术标签:

【中文标题】PyTorch 模型未收敛【英文标题】:PyTorch model not converging 【发布时间】:2020-11-13 11:53:44 【问题描述】:

我正在对一系列图像训练二元分类模型。 该模型源自torchvision中的resnet18,我将最后一个FC设为nn.Linear(512, 1)

损失函数为BCELoss

但是,即使经过 5000 次迭代,该模型也没有显示出任何收敛迹象。

我怀疑我可能在训练阶段做错了什么?但我找不到错误在哪里。

这是我的代码:

型号:

## Model
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models as models

resnet18 = models.resnet18(pretrained= True)
resnet18.fc = nn.Linear(512, 1)

参数、损失、优化器:

## parameter
epochs = 200
learning_rate = 0.1
momen = 0.9
batch = 8
criterion = nn.BCELoss()
resnet18.to(device)
opt = optim.SGD(resnet18.parameters(), lr = learning_rate, momentum = momen)

数据加载器:

# Generators
training_set = Dataset(X_train)
training_generator = torch.utils.data.DataLoader(training_set, batch_size= batch, shuffle=True)

validation_set = Dataset(X_test)
validation_generator = torch.utils.data.DataLoader(validation_set, batch_size=1, shuffle=False)

培训:

# training
history = []
for t in range(epochs):  
  for i, data in enumerate(training_generator, 0):

    inputs, labels = data
    # check if input size == batch size #
    if inputs.shape[0] < batch:
      break

#    print("labels", labels, labels.dtype)

    # move data to GPU #
    inputs, labels = inputs.to(device), labels.to(device)

    opt.zero_grad()
    # Prediction #
    y_pred = resnet18(inputs).view(batch,)
    y_pred = (y_pred > 0).float().requires_grad_()
#    print("y_pred", y_pred, y_pred.dtype)

    # Calculating loss #
    loss = criterion(y_pred, labels.view(batch,))
    loss.backward()
    opt.step()
    
    if i % 10 == 0:
      history.append(loss.item())
      print("Epoch: , iter: , loss: ".format(t, i, loss.item())


torch.save(resnet18, 'trained_resnet18.pt')

编辑:

损失值是这样的:

Epoch: 3, iter: 310, loss: 0.0
Epoch: 3, iter: 320, loss: 37.5
Epoch: 3, iter: 330, loss: 37.5
Epoch: 3, iter: 340, loss: 0.0
Epoch: 3, iter: 350, loss: 37.5
Epoch: 3, iter: 360, loss: 50.0
Epoch: 3, iter: 370, loss: 37.5
Epoch: 3, iter: 380, loss: 25.0
Epoch: 3, iter: 390, loss: 12.5

【问题讨论】:

不收敛是什么意思,几次迭代的损失值是多少? 我把它放在编辑中 查看我的回答,如果仍有问题,请及时更新。 【参考方案1】:

我相信错误在于以下行:

y_pred = (y_pred > 0).float().requires_grad_()

您尝试以一种奇怪的方式对模型预测进行二值化,我建议改为:

y_pred = torch.sigmoid(y_pred)

并将其传递给损失函数。

说明

模型的输出可以是任何值,但我们希望将这些值归一化以驻留在[0,1] 范围内。这正是 sigmoid 函数所做的。一旦我们得到[0,1] 范围内的值,与二进制标签的比较就会有意义,更接近 1 将是“1”,反之亦然。

您可以参考以下链接:https://www.youtube.com/watch?v=WsFasV46KgQ

【讨论】:

现在我得到了与张量相同的所有预测([1., 1., 1., 1., 1., 1., 1., 1.] 我尝试将 y_pred = (y_pred &gt; 0).float().requires_grad_() 注释掉并将损失函数切换为 BCEWithLogitsLoss(),它看起来像一个下降趋势。你认为这是正确的方法吗? 我猜torch.round() 如果值 >0 返回 1,如果值 y_pred = torch.sigmoid(y_pred) 正在工作!谢谢你。你能解释一下吗?我做了原始行,因为我在输入损失函数之前尝试将预测转换为 0, 1。所以这意味着我不应该那样做?

以上是关于PyTorch 模型未收敛的主要内容,如果未能解决你的问题,请参考以下文章

Pytorch GAN 模型未训练:矩阵乘法错误

PyTorch || 优化神经网络训练的17种方法

Pytorch 深度卷积网络在 CIFAR10 上不收敛

基于pytorch平台分类模型训练调式心得

PyTorch-线性回归_SGD_动量梯度下降

pytorch-04-激活函数