PyTorch单变量线性回归斜率始终错误问题排查求助
单变量线性回归模型斜率错误、损失偏高的排查方向
1. 数据未做标准化/归一化
梯度下降类优化器(SGD、Adam)对输入特征和目标变量的尺度极其敏感。scikit-learn的LinearRegression基于最小二乘法求解,不受特征尺度影响;但PyTorch的优化器依赖梯度更新,若身高、体重的数值尺度差异(或绝对值过大),会导致梯度步长难以适配,模型无法收敛到最优解。
解决方法:
对输入特征(身高)做标准化处理(减均值除以标准差),目标变量(体重)可选择标准化或保留原尺度:
# 假设female_data是筛选后的女性数据集 height_mean = female_data['Height'].mean() height_std = female_data['Height'].std() # 仅标准化输入特征 female_data['Height'] = (female_data['Height'] - height_mean) / height_std # 若同时标准化目标,后续可反转换回原尺度 weight_mean = female_data['Weight'].mean() weight_std = female_data['Weight'].std() female_data['Weight'] = (female_data['Weight'] - weight_mean) / weight_std
2. 模型输入/输出维度不匹配
若输入特征的维度为(batch_size,)而非(batch_size, 1),或标签维度与模型输出维度不匹配,会导致损失计算时的广播错误,间接影响梯度更新方向,最终使模型参数偏离最优值。
解决方法:
确保输入和标签的维度与模型输出一致:
# 数据加载时,为输入添加维度 inputs = torch.tensor(female_data['Height'].values, dtype=torch.float32).unsqueeze(1) targets = torch.tensor(female_data['Weight'].values, dtype=torch.float32).unsqueeze(1) # 模型定义需保持输入输出为1维 class LinearRegressor(nn.Module): def __init__(self): super().__init__() self.linear = nn.Linear(1, 1) def forward(self, x): return self.linear(x)
3. 学习率设置不合理
即使更换优化器,若学习率过大,模型会在最优值附近震荡;学习率过小,训练轮次不足时无法收敛到最优解。尤其在数据未标准化的情况下,过大的学习率会直接导致参数更新失控。
解决方法:
- 尝试缩小学习率(如SGD用
lr=0.001,Adam用默认0.001但需配合数据标准化) - 加入学习率调度器,随训练轮次逐步降低学习率:
optimizer = torch.optim.SGD(model.parameters(), lr=0.001) scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=10, gamma=0.1) # 训练循环中更新学习率 for epoch in range(epochs): # 训练步骤... scheduler.step()
4. 数据处理逻辑错误
需确认以下几点:
- 是否正确筛选了女性数据(如
female_data = data[data['Gender'] == 'Female'],注意字符串大小写是否匹配) - 是否将特征与标签搞反(如误把体重当输入、身高当标签)
- DataLoader是否存在重复采样或数据打乱的异常(如
shuffle=True是否合理,是否遗漏了drop_last=False导致样本数不完整)
5. 损失计算的细节差异
scikit-learn的MSE是全数据集总误差除以样本数;PyTorch的nn.MSELoss默认reduction='mean',即每个batch内的误差均值,若训练时用小批次,最终epoch的平均损失可能与全数据集MSE存在偏差。
解决方法:
训练结束后,用全数据集计算MSE,与scikit-learn结果对比:
model.eval() with torch.no_grad(): full_inputs = torch.tensor(female_data['Height'].values, dtype=torch.float32).unsqueeze(1) full_outputs = model(full_inputs) full_mse = nn.MSELoss()(full_outputs, torch.tensor(female_data['Weight'].values, dtype=torch.float32).unsqueeze(1)).item() print(f"全数据集MSE: {full_mse}")
内容的提问来源于stack exchange,提问作者Timo Junolainen
相关产品推荐
相关产品推荐

