逻辑斯蒂回归(Logistic Regression)虽然名字里带着"回归"二字,但实际上它是解决分类问题的经典算法。我第一次接触这个概念时也困惑过,后来在实际项目中才真正理解它的精妙之处。
举个生活中的例子:假设我们要预测学生考试是否及格(及格/不及格两类),输入是学习时间,输出是概率值。普通线性回归的输出范围是负无穷到正无穷,而我们需要的是0-1之间的概率值,这时候逻辑斯蒂回归就派上用场了。它通过sigmoid函数将线性输出映射到(0,1)区间,完美解决了二分类问题。
在PyTorch中实现逻辑斯蒂回归时,有几个关键点需要注意:
注意:初学者常犯的错误是混淆逻辑斯蒂回归和线性回归的适用场景。记住:预测连续值用线性回归,预测类别概率用逻辑斯蒂回归。
python复制x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[0], [0], [1]])
这个简单的数据集表示:
在实际项目中,数据通常会复杂得多。我建议先用小数据集验证模型正确性,再扩展到真实数据。数据预处理时要注意:
python复制class LogisticRegressionModel(torch.nn.Module):
def __init__(self):
super(LogisticRegressionModel, self).__init__()
self.linear = torch.nn.Linear(1, 1)
def forward(self, x):
y_pred = F.sigmoid(self.linear(x))
return y_pred
这个模型结构看似简单,但有几个设计要点:
nn.Linear(1,1)定义了一个单层线性网络,输入输出维度都是1F.sigmoid将线性输出转换为概率值我在实际项目中发现,有时需要调整初始化方式。PyTorch默认使用均匀初始化,但对于某些数据分布,使用nn.init.xavier_normal_可能效果更好。
python复制criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
BCELoss(二元交叉熵)的计算公式是:
code复制Loss = -[y*log(p) + (1-y)*log(1-p)]
其中y是真实标签,p是预测概率。
关于size_average=False参数:
reduction='sum'或'mean'优化器选择SGD(随机梯度下降)是最基础的,对于逻辑斯蒂回归通常够用。但在实际项目中,我经常尝试:
python复制for epoch in range(1000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
optimizer.zero_grad()
loss.backward()
optimizer.step()
这个训练循环包含了深度学习最基本的流程:
我建议添加以下改进:
python复制x = np.linspace(0,10,200)
x_t = torch.Tensor(x).view((200,1))
y_t = model(x_t)
y = y_t.data.numpy()
plt.plot(x,y)
plt.plot([0,10],[0.5,0.5],c='r')
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()
plt.show()
这段可视化代码展示了模型在整个输入范围内的预测结果。红线是决策边界(p=0.5),表示模型认为学习时间超过这个点后,通过考试的概率大于50%。
在实际项目中,我还会:
python复制optimizer = torch.optim.SGD(model.parameters(), lr=0.01, weight_decay=0.1)
维度不匹配错误:
view()或unsqueeze()调整维度梯度爆炸/消失:
预测结果不合理:
逻辑斯蒂回归虽然简单,但在实际项目中非常有用:
对于多分类问题,可以使用Softmax回归(逻辑斯蒂回归的推广),在PyTorch中对应nn.CrossEntropyLoss。
我在实际项目中发现,逻辑斯蒂回归配合特征工程往往能取得不错的效果,而且模型解释性强,这对业务方理解非常重要。