
本文旨在解决pytorch模型训练后准确率无法提升,甚至低于随机猜测的常见问题。文章将深入分析导致此问题的一个关键评估逻辑错误——即在测试循环中未正确累计预测结果,并提供详细的解决方案与pytorch模型评估的最佳实践,旨在帮助开发者构建更健壮、准确的机器学习模型。
在深度学习模型开发过程中,我们经常会遇到模型训练效果不理想的情况,例如经过数百个 Epoch 后,模型的准确率仍然停滞不前,甚至低于随机猜测。这往往令人困惑,因为我们可能已经尝试调整了批量大小、网络层数、学习率等超参数。然而,有时问题的根源并非出在模型结构或训练参数上,而是隐藏在模型评估的逻辑中。本文将通过一个具体的案例,详细剖析这种常见的评估错误,并提供一套完善的解决方案和最佳实践。
我们来看一个典型的PyTorch分类模型训练与评估代码示例,该模型旨在对SDSS数据集进行三分类。
import torch
import torch.nn as nn
import numpy as np
from torch.utils.data import Dataset, DataLoader
import torch.optim
# ... (device config, hyperparams, SDSS Dataset classes) ...
class NeuralNet(nn.Module):
def __init__(self, input_size, hidden_size, num_classes):
super(NeuralNet,self).__init__()
self.l1 = nn.Linear(input_size, hidden_size)
self.relu = nn.LeakyReLU()
self.l2 = nn.Linear(hidden_size, num_classes)
def forward(self, x):
out = self.l1(x)
out = self.relu(out)
out = self.l2(out)
return out
model = NeuralNet(input_size, hidden_size, num_classes)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
# ... (training loop) ...
# Test loop (problematic part)
with torch.no_grad():
n_correct = 0 # 初始化正确预测数
n_samples = 0 # 初始化样本总数
for inputs, labels in test_loader:
labels = labels.to(device)
outputs = model(inputs)
# inputs = torch.flatten(inputs) # 此行在模型前向传播后,不影响计算,但冗余
labels = torch.flatten(labels) # 将标签从 [batch_size, 1] 转换为 [batch_size]
_, predictions = torch.max(outputs, 1) # 获取预测类别
n_samples += labels.shape[0] # 累计样本总数
n_correct = (predictions == labels).sum().item() # 错误:每次循环都重新赋值,而非累计
acc = 100 * n_correct / n_samples
print(f'accuracy = {acc}')在上述代码中,模型训练过程看似正常,但在测试(评估)阶段,计算准确率的逻辑存在一个关键性错误。
错误的核心:n_correct 的赋值问题 在测试循环内部,计算每个批次正确预测数量的代码是:
n_correct = (predictions == labels).sum().item()
这里使用了赋值操作符 =,这意味着在每次迭代中,n_correct 都会被当前批次的正确预测数 覆盖,而不是与之前批次的正确预测数 累加。因此,最终 n_correct 的值将仅仅是 最后一个批次 的正确预测数,而非整个测试集上的总和。由于 n_samples 是正确累加的,这会导致计算出的准确率极低,甚至低于随机猜测,因为它只反映了测试集中一小部分数据的表现。
冗余操作:inputs = torch.flatten(inputs) 在训练和测试循环中,都存在一行 inputs = torch.flatten(inputs)。由于这行代码在 outputs = model(inputs) 之后执行,它不会影响模型的前向传播,因为模型已经接收了原始形状的 inputs。虽然它不会直接导致准确率问题,但它是冗余代码,可能引起混淆。对于 nn.Linear 层,它期望输入是 (batch_size, input_features) 的形状,如果 inputs 的原始形状就是 (batch_size, input_size),则无需进行 flatten 操作。
解决上述问题的关键在于正确地累计 n_correct。只需将 = 赋值操作符替换为 += 累加操作符即可。
# Test loop (corrected part)
with torch.no_grad():
n_correct = 0
n_samples = 0
for inputs, labels in test_loader:
labels = labels.to(device)
outputs = model(inputs)
labels = torch.flatten(labels) # 保持标签形状转换,以适应CrossEntropyLoss
_, predictions = torch.max(outputs, 1)
n_samples += labels.shape[0]
# 修正:将赋值操作改为累加操作
n_correct += (predictions == labels).sum().item()
acc = 100 * n_correct / n_samples
print(f'accuracy = {acc}')通过这一简单的修改,n_correct 将正确地累加整个测试集中的正确预测数,从而计算出真实的模型准确率。
为了避免类似的评估错误并确保模型性能的准确反映,以下是一些PyTorch模型评估的最佳实践:
正确累计评估指标
使用 torch.no_grad()
模型切换到评估模式
数据预处理与标签处理
超参数与模型结构
训练集、验证集和测试集划分
模型训练准确率不佳,甚至低于随机猜测,不总是意味着模型或超参数的选择有误。有时,问题可能出在看似微小的评估逻辑细节上。本文通过一个具体的案例,揭示了在PyTorch模型评估中,n_correct 变量未正确累计的常见错误,并提供了修正方案。同时,我们强调了PyTorch模型评估的最佳实践,包括正确累计指标、使用 torch.no_grad() 和 model.eval(),以及注意数据和标签的预处理。通过对这些细节的关注和实践,开发者可以更准确地评估模型性能,从而构建出更可靠、高效的深度学习模型。
以上就是解决PyTorch模型训练准确率不佳的问题:深入理解评估逻辑的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号