为何PyTorch二元分类模型训练准确率始终维持在0.5左右?
问题诊断与修复方案
你的二元分类器任务是线性可分的(决策边界为x1=x2),但训练准确率始终卡在随机猜测水平(~50%),核心问题集中在标签逻辑、学习率设置、模型结构冗余以及数据集分布不一致这几个方面:
关键问题分析
- 标签逻辑与任务预期反向:你预期
x1<x2时输出1,但代码中label_wo=((input_wo[:,0]>input_wo[:,1])).float()是x1>x2时标记为1,虽然这不会直接导致准确率卡壳,但会让模型学到的规则与预期完全相反。 - 学习率过低:Adam优化器用
lr=0.0001对于这个简单任务来说太小,参数更新速度极慢,甚至可能陷入局部最优。 - ReLU层破坏线性边界学习:任务本身是线性可分的,但中间的ReLU层会截断线性变换后的特征,导致模型无法捕捉到
x1-x2这个核心线性特征,梯度传递也会被削弱。 - 训练/验证集分布不一致:训练用
torch.randn(标准正态分布),验证用torch.rand([0,1]均匀分布),分布差异会让验证指标无法准确反映模型真实性能。
修复步骤
1. 修正标签逻辑
将标签改为符合任务预期的逻辑:
# 原代码:x1>x2时标记为1,改为x1<x2时标记为1 label_wo = ((input_wo[:,0] < input_wo[:,1])).float().reshape(-1,1) label_val = ((input_val[:,0] < input_val[:,1])).float().reshape(-1,1)
2. 调大学习率
把Adam的学习率调整到适合简单任务的范围,比如0.01或0.001:
optimizer_wo = optim.Adam(model_wo.parameters(), lr=0.01)
3. 简化模型结构(推荐)
因为任务是线性可分的,不需要多层ReLU,单层Linear+Sigmoid就能完美解决问题:
class Classifier(nn.Module): def __init__(self): super(Classifier, self).__init__() self.layer = nn.Linear(2, 1) self.sigmoid = nn.Sigmoid() def forward(self, x): x = self.layer(x) x = self.sigmoid(x) return x
如果坚持使用三层结构,必须去掉ReLU层(线性层叠加仍为线性,ReLU会破坏必要的特征关系):
class Classifier(nn.Module): def __init__(self): super(Classifier, self).__init__() self.layer1=nn.Linear(2,2) self.layer2=nn.Linear(2,2) self.layer3=nn.Linear(2,1) self.sigmoid=nn.Sigmoid() def forward(self, x): x = self.layer1(x) x = self.layer2(x) x = self.layer3(x) x = self.sigmoid(x) return x
4. 统一数据集分布
训练和验证集使用相同分布,比如都用标准正态分布:
# 训练集 input_wo = torch.randn((1000,2)) # 验证集 input_val = torch.randn((1000,2))
修复后效果
调整后,训练100轮左右就能看到准确率快速上升到99%以上,loss降至接近0,完全符合任务预期。
内容的提问来源于stack exchange,提问作者beginner
相关产品推荐
相关产品推荐

