PyTorch中验证准确率超100%问题排查求助
解决乳腺癌图像分类项目中验证准确率超100%的问题
核心问题分析
- 准确率变量未重置:
validation_accuracy在循环外初始化,每次epoch都会在上一次结果上累加,导致数值持续增大远超合理范围。 - 超参数未实际生效:随机搜索中选中的
batch_size没有被使用,数据加载器是提前用固定BATCH_SIZE创建的,等于白搜这个参数。 - 缺失训练流程:代码里只执行了验证循环,完全没有训练模型的步骤,一直在用初始化的随机权重模型跑验证,准确率毫无意义。
修正后的代码
1. 数据加载部分(适配动态batch_size)
将数据加载器的创建逻辑移到超参数搜索循环内,每次根据选中的batch_size生成对应加载器:
import torch.utils import torch.utils.data from torchvision.transforms import transforms import torch.utils.data as data transformed_data = transforms.Compose([ transforms.ToTensor() ]) training_dataset = DataSetClass(split="train", transform=transformed_data, download=download) train_size = int(training_ratio * len(training_dataset)) validation_size = int(validation_ratio * len(training_dataset)) testing_size = len(training_dataset) - train_size - validation_size train_set, validation_set, testing_dataset = torch.utils.data.random_split( training_dataset, [train_size, validation_size, testing_size] ) # 不再提前创建dataloader,放到后续搜索循环中
2. 超参数搜索与完整训练验证流程
import torch.optim as optim import numpy as np import torch.nn as nn # 定义超参数空间 lr_space = [0.01, 0.02, 0.03, 0.04, 0.05] epochs_space = [10, 20, 30, 40, 50] batch_size_space = [32, 64, 128, 256] best_accuracy = 0.0 best_hyperparameters = None # 执行随机搜索 for _ in range(100): # 随机选取超参数 lr = np.random.choice(lr_space) epochs = np.random.choice(epochs_space) batch_size = np.random.choice(batch_size_space) # 每次搜索重新初始化模型,避免历史训练影响 network = ExtendedNetwork(resnet18) network.to(device=device) # 根据选中的batch_size创建数据加载器 train_loader = data.DataLoader(dataset=train_set, batch_size=batch_size, shuffle=True) validation_loader = data.DataLoader(dataset=validation_set, batch_size=2*batch_size, shuffle=False) optimizer = optim.Adam(network.parameters(), lr=lr) loss_function = nn.BCEWithLogitsLoss() # 训练阶段 for epoch in range(epochs): network.train() for inputs, targets in train_loader: inputs, targets = inputs.to(device), targets.to(device) optimizer.zero_grad() output = network(inputs) # 确保目标值形状与输出匹配,BCEWithLogitsLoss要求输入维度一致 loss = loss_function(output, targets.float().unsqueeze(1)) loss.backward() optimizer.step() # 验证阶段 network.eval() validation_accuracy = 0.0 # 每次epoch重置准确率 with torch.no_grad(): for inputs, targets in validation_loader: inputs, targets = inputs.to(device), targets.to(device) output = network(inputs) # 统计当前batch的正确样本数 preds = torch.sigmoid(output) >= 0.5 correct = (preds == targets.unsqueeze(1)).sum().item() validation_accuracy += correct # 计算整体验证准确率(正确数/总验证样本数) validation_accuracy /= len(validation_set) print(f'Epoch {epoch+1}, Validation Accuracy: {validation_accuracy:.4f}') # 更新最佳结果 if validation_accuracy > best_accuracy: best_accuracy = validation_accuracy best_hyperparameters = {'lr': lr, 'epochs': epochs, 'batch_size': batch_size} print(f'Best Accuracy: {best_accuracy:.4f}') print('Best Hyperparameters:', best_hyperparameters)
关键注意点
- 准确率计算逻辑:代码中直接实现了二分类准确率的计算,替代原有的
accuracy函数,避免函数内部逻辑错误导致的异常数值。 - 模型重置:每次超参数搜索都重新初始化模型,保证不同超参数的训练是独立的。
- 超参数生效:将数据加载器的创建放到搜索循环内,确保选中的
batch_size实际作用于训练和验证。
内容的提问来源于stack exchange,提问作者zkhan122
相关产品推荐
相关产品推荐

