You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:46:21