1. 逻辑回归预测实战:PyTorch实现指南

当你需要解决二分类问题时(比如判断邮件是否为垃圾邮件、预测用户是否会点击广告),逻辑回归往往是第一个值得尝试的算法。虽然名为"回归",但它实际上是分类任务的利器。今天我们就用PyTorch这个深度学习框架来实现逻辑回归预测——没错,虽然逻辑回归是传统机器学习方法,但用PyTorch实现能让我们更灵活地控制模型细节,也为后续过渡到神经网络打下基础。

2. 核心原理与PyTorch优势

2.1 逻辑回归数学本质

逻辑回归的核心是sigmoid函数:σ(z) = 1/(1+e⁻ᶻ),它将线性组合z=wᵀx+b映射到(0,1)区间,输出可解释为概率。决策边界通常设为0.5,即预测概率>0.5为正类。

与scikit-learn等传统实现不同,PyTorch版本让我们可以:

  • 自定义损失函数(BCELoss + 正则化项)
  • 灵活调整优化器(SGD/Adam等)
  • 方便接入GPU加速
  • 后续无缝升级为神经网络层

2.2 数据准备要点

from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler

data = load_breast_cancer()
X = StandardScaler().fit_transform(data.data)
y = data.target.reshape(-1, 1)

# 转换为PyTorch张量
X_tensor = torch.FloatTensor(X)
y_tensor = torch.FloatTensor(y)

关键提示:二分类任务中,务必确保标签y是float类型且为列向量(shape=[n_samples,1]),否则后续BCELoss会报错

3. PyTorch模型实现详解

3.1 模型定义三种方式

# 方法1:Sequential式(类似Keras)
model = nn.Sequential(
    nn.Linear(30, 1),
    nn.Sigmoid()
)

# 方法2:类继承式(推荐)
class LogisticRegression(nn.Module):
    def __init__(self, input_dim):
        super().__init__()
        self.linear = nn.Linear(input_dim, 1)
    
    def forward(self, x):
        return torch.sigmoid(self.linear(x))

# 方法3:函数式API
linear_layer = nn.Linear(30, 1)
def model(x):
    return torch.sigmoid(linear_layer(x))

3.2 训练循环关键配置

criterion = nn.BCELoss()  # 二分类交叉熵
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)

for epoch in range(100):
    # 前向传播
    outputs = model(X_tensor)
    loss = criterion(outputs, y_tensor)
    
    # 反向传播
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    # 每10轮打印损失
    if (epoch+1) % 10 == 0:
        print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')

实测技巧:Adam优化器通常比SGD收敛更快,但对学习率更敏感。建议初始设为0.01,如果震荡剧烈可尝试0.001

4. 高级功能与生产级改进

4.1 添加L2正则化

PyTorch不会自动实现正则化,需要手动添加:

l2_lambda = 0.001
l2_norm = sum(p.pow(2.0).sum() for p in model.parameters())
loss = criterion(outputs, y_tensor) + l2_lambda * l2_norm

4.2 自定义评估指标

除了准确率,建议监控这些指标:

with torch.no_grad():
    probas = model(X_test)
    predictions = (probas > 0.5).float()
    
    # 计算混淆矩阵
    TP = ((predictions == 1) & (y_test == 1)).sum().item()
    FP = ((predictions == 1) & (y_test == 0)).sum().item()
    TN = ((predictions == 0) & (y_test == 0)).sum().item()
    FN = ((predictions == 0) & (y_test == 1)).sum().item()
    
    precision = TP / (TP + FP + 1e-7)
    recall = TP / (TP + FN + 1e-7)
    f1 = 2 * (precision * recall) / (precision + recall + 1e-7)

4.3 部署推理优化

生产环境中建议:

  1. 使用 torch.jit.script 导出模型
  2. 对输入数据启用 torch.no_grad()
  3. 批量处理提高吞吐量
# 示例推理代码
@torch.jit.script
def predict(x: torch.Tensor) -> torch.Tensor:
    return model(x)

# 使用时
with torch.no_grad():
    batch_outputs = predict(input_batch)

5. 常见问题排查手册

5.1 损失值不下降

  • 检查数据是否未标准化(特别是数值型特征)
  • 尝试调整学习率(0.1, 0.01, 0.001梯度测试)
  • 确认标签y的shape是[n_samples,1]而非[n_samples]

5.2 预测结果全为0或1

  • 降低学习率防止梯度爆炸
  • 检查特征与目标的相关性
  • 添加权重初始化:
nn.init.xavier_uniform_(model.linear.weight)
nn.init.zeros_(model.linear.bias)

5.3 GPU相关错误

如果遇到CUDA错误:

  1. 确保所有数据在同一设备:
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
X_tensor = X_tensor.to(device)
  1. 检查PyTorch的CUDA版本是否与显卡驱动匹配

6. 与其他框架对比实践

6.1 与scikit-learn版本对比

from sklearn.linear_model import LogisticRegression as SKLogistic

sk_model = SKLogistic(penalty='l2', C=1.0)
sk_model.fit(X_train, y_train.ravel())

# 比较权重差异
print("PyTorch weights:", model.linear.weight.data)
print("sklearn weights:", sk_model.coef_)

典型差异:

  • sklearn默认使用L2正则化(通过C参数控制)
  • PyTorch版本需要手动实现正则化
  • sklearn自动处理特征标准化(当设置penalty='l2'时)

6.2 扩展为神经网络

只需修改模型定义即可升级:

class NNClassifier(nn.Module):
    def __init__(self, input_dim):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(input_dim, 64),
            nn.ReLU(),
            nn.Linear(64, 1),
            nn.Sigmoid()
        )
    
    def forward(self, x):
        return self.net(x)

这种渐进式升级正是PyTorch的优势所在——从简单的逻辑回归开始,逐步构建更复杂的模型,而无需切换框架

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐