You need to enable JavaScript to run this app. PyTorch自定义ConvNet训练准确率为0且损失无变化的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

PyTorch自定义ConvNet训练准确率为0且损失无变化的问题排查

问题排查清单

按照出现概率从高到低逐一排查:

1. 检查标签数据类型

  • nn.CrossEntropyLoss 处理离散分类任务时,要求标签必须是 torch.long 类型,形状为 (batch_size,)。如果标签被存储为浮点型(比如torch.float32),PyTorch不会抛出形状不匹配的报错,反而会将其误判为软标签输入,导致损失计算逻辑异常、梯度无法正确回传,直接表现为损失恒定不变、训练准确率始终为0。
  • 验证方法:在训练循环内增加一行打印:print(labels.dtype, labels.shape),确认标签类型为long、形状为一维的批次向量。

2. 验证梯度回传链路完整性

损失完全不变化的核心诱因是梯度没有真正作用到模型参数上,可通过以下方式定位:

  • 第一次执行loss.backward()后,打印任意一层参数的梯度值,例如 print(model.fc[1].weight.grad),如果梯度全为0,说明计算图断连。
  • 常见的断连场景:
    • 模型和数据没有移动到同一计算设备(CPU/GPU),导致前向计算脱离梯度追踪范围
    • 手动将模型参数的requires_grad设置为False
    • 优化器绑定的参数列表为空,可通过len(list(optimizer.param_groups[0]['params']))检查,正常返回值应等于模型的可训练参数总数

3. 修正全连接层结构缺陷

当前全连接层堆叠两个线性层却没有中间激活函数,虽不会直接导致损失不收敛,但会大幅限制模型拟合能力。补充激活函数的正确写法如下:

self.fc = nn.Sequential(
    nn.Linear(512*3*3, 512),
    nn.ReLU(),  # 补充缺失的非线性激活
    nn.Linear(512, numclasses)
)

4. 规范训练循环执行顺序

当前训练循环的梯度清零操作放在了前向计算、损失计算之后,虽逻辑上可运行,但容易引入梯度累积的隐蔽问题。调整为PyTorch官方推荐的顺序:

for i, (images, labels) in enumerate(train_loader):
    optimizer.zero_grad()  # 每个批次开头先清零梯度
    outputs = model(images)
    loss = criterion(outputs, labels)
    loss.backward()
    optimizer.step()
    
    # 后续准确率统计逻辑
    total = labels.size(0)
    _, predicted = torch.max(outputs.data, 1)
    correct = (predicted == labels).sum().item()

5. 校验数据集标签合法性

检查标签取值范围是否完全落在[0, num_classes-1]区间内,确认图像和标签是一一匹配的,没有出现标签被错误设置为固定值、样本与标签错序的问题。如果一个100类分类任务的随机初始化模型连1%的随机猜测准确率都达不到,基本可以确认标签逻辑存在硬错误。


内容的提问来源于stack exchange,提问作者Miton4

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 13:15:03