PyTorch训练CNN模型:如何在训练过程中添加验证误差计算
如何在PyTorch CNN训练流程中添加验证误差计算逻辑
嘿,我来帮你搞定这个事儿!其实在PyTorch里给训练流程加验证误差计算挺直观的,核心就是把训练阶段和验证阶段分开处理——训练时让模型保持训练模式(开启dropout、batchnorm的动态更新),验证时切换到评估模式(关闭这些训练专属的层行为),再用验证数据集计算损失和指标。我结合你的Net模型给你一步步说明:
1. 先准备好验证数据集的加载器
首先你得有划分好的验证数据集,用DataLoader和训练集一样加载就行,注意验证集不需要shuffle:
# 假设你已经定义好验证集的Dataset对象val_dataset val_loader = torch.utils.data.DataLoader( val_dataset, batch_size=32, # 和训练集batch_size保持一致或者按需调整 shuffle=False )
2. 修改训练循环,嵌入验证逻辑
每个epoch的训练结束后(或者你想中途验证的话也可以),跑一遍验证集的前向传播。这里要注意两个关键操作:model.eval()切换评估模式,torch.no_grad()禁用梯度计算(节省内存和计算资源)。
结合你的模型,完整的训练循环示例如下:
# 初始化核心组件 model = Net() device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model.to(device) criterion = nn.CrossEntropyLoss() # 假设是分类任务,可根据你的任务替换损失函数 optimizer = torch.optim.Adam(model.parameters(), lr=0.001) num_epochs = 10 for epoch in range(num_epochs): # -------------------------- 训练阶段 -------------------------- model.train() # 切换到训练模式,开启dropout、batchnorm的训练行为 train_total_loss = 0.0 for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() # 清空梯度 output = model(data) # 前向传播 loss = criterion(output, target) # 计算损失 loss.backward() # 反向传播 optimizer.step() # 更新参数 train_total_loss += loss.item() * data.size(0) # 累计批次损失 # 计算当前epoch的平均训练损失 avg_train_loss = train_total_loss / len(train_loader.dataset) # -------------------------- 验证阶段 -------------------------- model.eval() # 切换到评估模式,关闭dropout、固定batchnorm的均值方差 val_total_loss = 0.0 correct_preds = 0 with torch.no_grad(): # 禁用梯度计算,避免不必要的内存消耗 for data, target in val_loader: data, target = data.to(device), target.to(device) output = model(data) # 累计验证损失 val_total_loss += criterion(output, target).item() * data.size(0) # 计算分类准确率(以分类任务为例,可替换成你需要的指标) pred = output.argmax(dim=1, keepdim=True) correct_preds += pred.eq(target.view_as(pred)).sum().item() # 计算当前epoch的平均验证损失和准确率 avg_val_loss = val_total_loss / len(val_loader.dataset) val_acc = correct_preds / len(val_loader.dataset) # 打印训练&验证结果 print(f"Epoch {epoch+1}/{num_epochs}") print(f"训练损失: {avg_train_loss:.4f} | 验证损失: {avg_val_loss:.4f} | 验证准确率: {val_acc:.4f}\n")
3. 补全你的Net模型fc层
看你代码里的self.fc1 = torch.nn.Linear(...还没写完,这里要注意fc层的输入维度是卷积池化后特征图的总尺寸。比如假设你的输入是28x28的单通道图片:
- conv1输出尺寸:28-5+1=24,maxpool后变成12x12
- conv2输出尺寸:12-5+1=8,maxpool后变成4x4
所以fc1的输入维度应该是64*4*4=1024,也就是:
self.fc1 = nn.Linear(64*4*4, 512) self.fc2 = nn.Linear(512, 10) # 假设是10分类任务,替换成你的输出类别数
额外小贴士
- 如果验证集很大,可以每隔2-3个epoch再跑一次验证,节省训练时间
- 可以把验证逻辑封装成独立函数,让代码更整洁:
def calculate_val_metrics(model, val_loader, criterion, device): model.eval() total_loss = 0.0 correct = 0 with torch.no_grad(): for data, target in val_loader: data, target = data.to(device), target.to(device) output = model(data) total_loss += criterion(output, target).item() * data.size(0) pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() avg_loss = total_loss / len(val_loader.dataset) acc = correct / len(val_loader.dataset) return avg_loss, acc
之后在训练循环里直接调用val_loss, val_acc = calculate_val_metrics(model, val_loader, criterion, device)即可
内容的提问来源于stack exchange,提问作者Edamame
相关产品推荐
相关产品推荐

