PyTorch训练神经网络时准确率无提升的问题求助
问题排查与解决:测试准确率始终不变的原因及修复方案
核心问题分析
1. 准确率计算逻辑错误
模型最后一层输出是单维度张量(out_features=1),使用torch.argmax(out, axis=1)完全错误——argmax在axis=1上没有元素可选取,导致所有预测结果固定为0,准确率直接等于数据集里类别0的占比,自然不会变化。
2. 损失函数与优化器未定义
训练代码中直接使用loss和optimizer但未初始化,即使代码能运行,也大概率用了不匹配的损失函数类型。对于sigmoid输出的二分类任务,必须使用BCELoss。
3. 目标张量格式不匹配
resultsTensor是整数类型且形状为[N],但BCELoss要求目标张量是float类型且形状与模型输出一致(即[N,1]),格式不匹配会导致损失计算异常,模型参数无法有效更新。
4. 可选优化点
- 把batch_size设为整个数据集,每次epoch仅更新一次参数,训练效率极低;
- 固定bias为1且关闭梯度,会限制模型拟合能力,除非有明确业务需求,否则不建议这么做。
修复后的完整代码
1. 模型部分(微调)
import torch class Classifier(torch.nn.Module): def __init__(self): super().__init__() self.layer1 = torch.nn.Linear(in_features=6, out_features=2, bias=True) self.layer2 = torch.nn.Linear(in_features=2, out_features=1, bias=True) self.activation = torch.sigmoid def forward(self, x): x = self.activation(self.layer1(x)) x = self.activation(self.layer2(x)) return x model = Classifier() def setParameters(m): if type(m) == torch.nn.Linear: torch.nn.init.uniform_(m.weight.data, -0.3, 0.3) torch.nn.init.constant_(m.bias.data, 1) model.apply(setParameters) # 建议保留bias的梯度,除非有特殊业务需求 # model.layer1.bias.requires_grad = False # model.layer2.bias.requires_grad = False
2. 训练与评估部分(关键修复)
from google.colab import drive import random drive.mount('/content/drive') %cd drive/MyDrive/deeplearning/ass1/data numbers = [] results = [] with open('data.txt') as f: lines = f.readlines() random.shuffle(lines) for line in lines: digitsOfNumber = [int(x) for x in str(line[0:6])] resultInteger = int(line[7:8]) numbers.append(digitsOfNumber) results.append(resultInteger) # 输入张量保持float类型 numbersTensor = torch.Tensor(numbers) # 目标张量转为float并调整形状为[N,1],匹配模型输出格式 resultsTensor = torch.tensor(results, dtype=torch.float32).unsqueeze(1) dataset = torch.utils.data.TensorDataset(numbersTensor, resultsTensor) trainsetSize = int(0.8 * len(dataset)) trainset, testset = torch.utils.data.random_split(dataset, [trainsetSize, len(dataset) - trainsetSize]) print(len(trainset), len(testset)) # 设置合理的batch_size,提升训练效率 testloader = torch.utils.data.DataLoader(testset, batch_size=32, shuffle=False) trainloader = torch.utils.data.DataLoader(trainset, batch_size=32, shuffle=True) # 修复准确率计算函数 def get_accuracy(model, dataloader): model.eval() correct = 0 total = 0 with torch.no_grad(): for x, y in dataloader: out = model(x) # 对sigmoid输出做阈值判断,得到二分类结果(0或1) pred = (out > 0.5).float() correct += (pred == y).sum().item() total += y.size(0) return correct / total # 初始化匹配任务的损失函数和优化器 loss_fn = torch.nn.BCELoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01) # 可根据训练情况调整学习率 epochs = 50 # 无需设置过大的epoch数,先观察训练趋势 losses = [] for epoch in range(epochs): train_loss = 0.0 model.train() for x, y in trainloader: optimizer.zero_grad() out = model(x) l = loss_fn(out, y) l.backward() optimizer.step() train_loss += l.item() * x.size(0) # 每个epoch结束后计算平均损失和测试准确率 avg_train_loss = train_loss / len(trainset) test_acc = get_accuracy(model, testloader) losses.append(avg_train_loss) print(f"Epoch {epoch+1}, Train Loss: {avg_train_loss:.4f}, Test Accuracy: {test_acc:.4f}") print("Final Test Accuracy: ", get_accuracy(model, testloader)) for name, param in model.named_parameters(): print(name, param)
验证修复效果
修复后,准确率会随着训练epoch增加逐步提升(若数据与模型匹配);若准确率仍无提升,可尝试调整学习率、增加模型层数/神经元数量,或检查数据集是否存在标签错误、数据分布异常等问题。
内容的提问来源于stack exchange,提问作者Eminent Emperor Penguin
相关产品推荐
相关产品推荐

