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 > 0).float().requires_grad_()
注释掉并将损失函数切换为 BCEWithLogitsLoss(),它看起来像一个下降趋势。你认为这是正确的方法吗?
我猜torch.round()
如果值 >0 返回 1,如果值
y_pred = torch.sigmoid(y_pred)
正在工作!谢谢你。你能解释一下吗?我做了原始行,因为我在输入损失函数之前尝试将预测转换为 0, 1。所以这意味着我不应该那样做?以上是关于PyTorch 模型未收敛的主要内容,如果未能解决你的问题,请参考以下文章