预训练VGG实现混凝土裂纹二分类时训练验证损失不下降求助
问题解决方案
你遇到的损失固定为0.693(二分类交叉熵的初始随机值)是代码存在多处逻辑错误导致模型完全没有被正常训练,具体错误及修正方式如下:
- 反向传播未实际执行:代码中
loss.backward未加括号,只是引用了方法本身,没有触发梯度计算,模型参数自始至终没有更新 - 优化器初始化位置错误:
optimizer = torch.optim.Adam(net.parameters(), lr=LEARNING_RATE)写在了batch循环内部,每处理一个batch就会重置优化器状态,之前迭代的梯度信息全部丢失 - 梯度未清零:每次迭代更新参数前没有清空上一轮的梯度,会导致梯度不断叠加,更新逻辑完全混乱
- 验证损失计算错误:验证集循环内直接对
val_loss赋值而非累加,输出的损失仅为最后一个batch的结果,无法反映全局情况 - 未加载预训练权重:你提到使用预训练VGG,但当前代码是手动从零搭建VGG结构,没有加载官方预训练权重,小数据集下从零训练收敛难度高
修正后的训练代码片段
# 如果你要使用预训练VGG,替换之前手动搭建VGG的部分即可,示例如下: # net = torchvision.models.vgg16(pretrained=True) # # 替换最后一层分类头适配二分类 # net.classifier[6] = nn.Linear(4096, 2) num_epochs = 15 min_val_loss = np.inf criterion = nn.CrossEntropyLoss() # 优化器放在循环外,仅初始化一次 optimizer = torch.optim.Adam(net.parameters(), lr=LEARNING_RATE) for epoch in range(num_epochs): train_loss = 0.0 net.train() for data, labels in train_data_loader: # 每轮迭代前先清空梯度 optimizer.zero_grad() target = net(data) loss = criterion(target, labels) # 加括号执行反向传播 loss.backward() optimizer.step() train_loss += loss.item() * data.size(0) val_loss = 0.0 net.eval() # 关闭梯度计算节省显存加快速度 with torch.no_grad(): for data, labels in val_data_loader: target = net(data) loss = criterion(target, labels) # 累加所有batch的损失 val_loss += loss.item() * data.size(0) # 损失计算除以样本总数而非batch数,结果更准确 print(f'Epoch {epoch+1} \t\t Training Loss: {train_loss/len(train_data)} \t\t Validation Loss: {val_loss/len(val_data)}') print('Finished Training')
按照上述内容修正后即可正常训练收敛。
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

