Logistic Regression模型无法学习,准确率约50%如何优化?
Logistic回归模型不收敛问题的解决方案
1. 数据预处理修正
- 特征标准化:Logistic回归对输入特征的尺度极度敏感,从初始loss高达13418来看,你的
xTrain数值范围过大,直接导致权重更新异常。必须先做标准化处理:from sklearn.preprocessing import StandardScaler import numpy as np # 转换为numpy数组处理,再转回tensor xTrain_np = xTrain.numpy().reshape(-1, 1) scaler = StandardScaler() xTrain_scaled = scaler.fit_transform(xTrain_np) xTrain = torch.tensor(xTrain_scaled, dtype=torch.float32) - 标签格式校验:
BCEWithLogitsLoss要求标签yTrain为float32类型,且形状与模型输出的logits完全一致。修正标签:# 确保标签是float类型,且和yLogits形状匹配 yTrain = yTrain.to(torch.float32).squeeze() - 数据有效性检查:验证
xTrain与yTrain是否存在相关性,如果两类样本的特征分布完全重叠,模型无法学习到区分性特征,只能随机猜测。可通过绘制散点图直观查看:import matplotlib.pyplot as plt plt.scatter(xTrain.numpy(), yTrain.numpy()) plt.xlabel('Feature') plt.ylabel('Label') plt.show()
2. 模型与训练逻辑修正
- 合理初始化模型参数:默认线性层初始化可能导致初始输出偏离合理范围,手动初始化偏差,让模型初始输出接近样本的正例比例:
class Logistic(nn.Module): def __init__(self, pos_ratio): super(Logistic, self).__init__() self.layer = nn.Linear(1, 1) # 初始化偏差,使初始sigmoid输出等于正样本比例 with torch.no_grad(): self.layer.bias.fill_(torch.log(torch.tensor(pos_ratio / (1 - pos_ratio)))) # 计算正样本比例 pos_ratio = yTrain.mean().item() model_0 = Logistic(pos_ratio) - 损失函数规范使用:
- 使用
BCELoss时,必须在模型输出后添加sigmoid层,否则输入损失函数的不是概率值,导致训练逻辑错误:
此时损失计算应为class Logistic(nn.Module): def __init__(self): super(Logistic, self).__init__() self.layer = nn.Linear(1, 1) self.sigmoid = nn.Sigmoid() def forward(self, x): return self.sigmoid(self.layer(x))loss = lossFunction(yPredicted, yTrain),无需额外调用sigmoid。 BCEWithLogitsLoss的用法是正确的(已内置sigmoid),但需确保标签格式正确。
- 使用
- 调整学习率:初始学习率
0.01过大,会导致权重更新震荡,无法收敛。尝试降低学习率:optimizer = torch.optim.Adam(params=model_0.parameters(), lr=0.001) - 校验准确率计算函数:确保
Accuracy函数逻辑正确,避免因指标计算错误误导判断:def Accuracy(yPred, yTrue): # 确保预测值和标签都是相同类型(比如float或int) correct = torch.eq(yPred.int(), yTrue.int()).sum().item() return (correct / len(yTrue)) * 100
3. 训练过程监控
- 绘制loss和准确率的变化曲线,观察是否有收敛趋势:
losses = [] accs = [] for epoch in range(1000): yLogits = model_0(xTrain).squeeze() yPredicted = torch.round(torch.sigmoid(yLogits)) loss = lossFunction(yLogits, yTrain) accuracy = Accuracy(yPredicted, yTrain) optimizer.zero_grad() loss.backward() optimizer.step() losses.append(loss.item()) accs.append(accuracy) if epoch % 100 == 0: print(f'epoch : {epoch}, loss: {loss.item():.4f}, accuracy: {accuracy:.1f}') # 绘制曲线 plt.figure(figsize=(12, 4)) plt.subplot(1, 2, 1) plt.plot(losses) plt.title('Training Loss') plt.subplot(1, 2, 2) plt.plot(accs) plt.title('Training Accuracy') plt.show() - 查看模型权重变化,训练前后打印
model_0.layer.weight和model_0.layer.bias,如果参数几乎无变化,说明梯度消失或优化器配置有误。
内容的提问来源于stack exchange,提问作者uddithmachiraju
相关产品推荐
相关产品推荐

