PyTorch中CNN分类器训练时各Epoch准确率计算异常求助
解决PyTorch CNN训练中Epoch准确率计算错误的问题
嘿,我一眼就看出问题啦——你现在计算训练准确率的时候,只用到了最后一个batch的outputs和labels,根本没把整个epoch里所有样本的预测结果累积起来!这就是为啥准确率总是在0、0.25、0.75这种奇怪的数值跳来跳去,完全反映不了模型在整个训练集上的真实表现。
下面是具体的修复方案,包含训练准确率和测试准确率的正确计算方式:
1. 调整训练阶段的准确率计算逻辑
我们需要在每个epoch内,对所有batch的预测结果进行累积统计,而不是只取最后一个batch的数据。修改后的代码如下:
def get_accuracy(pred, actual): assert len(pred) == len(actual) _, predicted = torch.max(pred.data, 1) correct = (predicted == actual).sum().item() return correct, len(actual) # 修改:返回正确数和样本数,方便累积统计 def train_model(model, trainloader, testloader, criterion, optimizer, epochs, device): for epoch in range(epochs): model.train() # 切换到训练模式,启用Dropout/BatchNorm等训练特有的层 running_loss = 0.00 total_correct_train = 0 total_samples_train = 0 for i, data in enumerate(trainloader, 0): inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # 累积损失和准确率统计 running_loss += loss.item() batch_correct, batch_total = get_accuracy(outputs, labels) total_correct_train += batch_correct total_samples_train += batch_total # 计算整个epoch的平均损失和训练准确率 avg_loss = running_loss / len(trainloader) training_accuracy = total_correct_train / total_samples_train * 100 # 转成百分比格式 # 计算测试准确率 test_accuracy = calculate_test_accuracy(model, testloader, device) # 打印结果 print('='*10, f'Iteration: {epoch+1}', '='*10) print(f'\nLoss: {avg_loss:.4f} \nTraining accuracy: {training_accuracy:.2f}% \nTest accuracy: {test_accuracy:.2f}%') print('Finished Training')
2. 实现测试准确率的计算函数
测试阶段需要关闭梯度计算(避免不必要的资源消耗),同时确保模型处于评估模式(禁用Dropout、固定BatchNorm统计量):
def calculate_test_accuracy(model, testloader, device): model.eval() # 切换到评估模式 total_correct_test = 0 total_samples_test = 0 with torch.no_grad(): # 关闭梯度计算,节省内存和计算时间 for data in testloader: inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) outputs = model(inputs) batch_correct, batch_total = get_accuracy(outputs, labels) total_correct_test += batch_correct total_samples_test += batch_total return (total_correct_test / total_samples_test) * 100 # 返回百分比形式的准确率
关键修改点说明
- 准确率累积:不再只取最后一个batch的结果,而是在每个batch中统计正确数和样本数,最终用整个epoch的总正确数除以总样本数,得到真实的训练准确率。
- 模型模式切换:训练时用
model.train(),测试时用model.eval(),确保模型层的行为符合当前阶段的需求。 - 梯度关闭:测试阶段用
torch.no_grad(),避免计算梯度,大幅降低内存占用和计算耗时。
这样修改后,你就能得到每个epoch真实的训练准确率和测试准确率了,不会再出现那种奇怪的固定数值啦!
内容的提问来源于stack exchange,提问作者inferense
相关产品推荐
相关产品推荐

