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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:20:21