PyTorch圆分类模型训练后预测值与预期完全反转问题排查
问题根源分析
你的预测结果完全反转的核心原因是数据集标签逻辑与你的期望相反,同时模型输出符号未适配这个反向标签:
sklearn.datasets.make_circles默认规则:生成的标签中,内圈样本为1,外圈样本为0,但你期望内圈为0、外圈为1,两者逻辑完全相反。- 你的模型
forward输出为x[:,0]² + x[:,1]² - r²:- 外圈点:
x²+y² > r²→ 输出为正,经sigmoid后概率趋近于1 - 内圈点:
x²+y² < r²→ 输出为负,经sigmoid后概率趋近于0
- 外圈点:
- 由于数据集标签是内圈1、外圈0,模型为了最小化损失,被迫学习到「正输出对应标签0,负输出对应标签1」的反向映射,最终导致预测结果与你的期望完全反转。而半径预测正确,说明模型已经准确找到了区分内外圈的边界,只是标签对应关系搞反了。
两种解决方法
方法一:修正数据集标签(推荐,直接匹配你的期望)
在生成数据集时反转标签,让内圈为0、外圈为1:
from sklearn.datasets import make_circles n_samples=1000 x, y = make_circles(n_samples, noise=0.03, random_state=42) # 反转标签:原内圈1→0,原外圈0→1 y = 1 - y X = torch.from_numpy(x).type(torch.float) Y = torch.from_numpy(y).type(torch.float) from sklearn.model_selection import train_test_split xtrain, xtest, ytrain, ytest = train_test_split(X, Y, test_size=0.2, random_state=42)
修改后,模型的输出逻辑(外圈输出正→对应标签1,内圈输出负→对应标签0)将完全匹配你的期望,训练后预测结果会符合预期。
方法二:修改模型输出符号(无需调整数据集)
如果你不想修改数据集,可以反转模型输出符号,让输出逻辑适配原数据集标签:
class cp(nn.Module): def __init__(self): super().__init__() self.r = nn.Parameter(torch.randn(1, requires_grad = True, dtype=torch.float)) def forward(self, x): # 反转输出符号:原输出为x²+y²-r²,改为r²-(x²+y²) return self.r**2 - (x[:, 0]**2 + x[:, 1]**2)
修改后模型输出逻辑变为:
- 内圈点:
x²+y² < r²→ 输出为正 → sigmoid后概率趋近于1(对应原数据集内圈标签1) - 外圈点:
x²+y² > r²→ 输出为负 → sigmoid后概率趋近于0(对应原数据集外圈标签0)
若要匹配你「内圈0、外圈1」的期望,只需在预测时将结果反转(1 - tf)即可。
验证方式
修改后,原ytrain[:10](tensor([1., 0., 0., 0., 1., 0., 1., 1., 0., 0.]))会变为tensor([0., 1., 1., 1., 0., 1., 0., 0., 1., 1.]),模型预测结果将与修正后的标签一致,符合你的预期。
内容的提问来源于stack exchange,提问作者Vigna Tej
相关产品推荐
相关产品推荐

