🎯 逻辑回归 — 分类准确率>80%

从回归到分类的优雅跳跃

📖 从线性回归到逻辑回归

线性回归输出连续值,而分类任务需要输出类别概率。逻辑回归通过Sigmoid函数将线性输出映射到[0,1]区间,实现概率预测与分类。

逻辑回归的数学架构: 线性部分: z = w₁x₁ + w₂x₂ + ... + wₙxₙ + b Sigmoid映射: σ(z) = 1 / (1 + e⁻ᶻ) 概率解释: P(y=1|X) = σ(z) P(y=0|X) = 1 - σ(z) 分类决策: ŷ = 1 if P(y=1|X) ≥ 0.5 else 0 损失函数(交叉熵): L = -(1/n) Σ [yᵢ·log(σ(zᵢ)) + (1-yᵢ)·log(1-σ(zᵢ))] 梯度: ∂L/∂wⱼ = (1/n) Σ (σ(zᵢ) - yᵢ) · xᵢⱼ 决策边界: w₁x₁ + w₂x₂ + b = 0 → 一条直线(2D) 多维时 → 超平面

Sigmoid函数的特性

性质公式意义
输出范围(0, 1)天然概率
单调递增σ'(z) > 0输入越大,P(y=1)越高
导数简洁σ'(z) = σ(z)(1-σ(z))梯度计算高效
对称性σ(-z) = 1 - σ(z)正负对称
z=0时σ(0) = 0.5决策边界

🔢 手写逻辑回归

import numpy as np

np.random.seed(42)

# 生成二分类数据
n = 200
X_class0 = np.random.multivariate_normal([2, 2], [[1, 0.3], [0.3, 1]], n//2)
X_class1 = np.random.multivariate_normal([5, 5], [[1, 0.3], [0.3, 1]], n//2)
X = np.vstack([X_class0, X_class1])
y = np.array([0]*(n//2) + [1]*(n//2))

# 添加偏置项
X_with_bias = np.c_[np.ones(n), X]

def sigmoid(z):
    """Sigmoid激活函数"""
    return 1 / (1 + np.exp(-np.clip(z, -500, 500)))

# 梯度下降训练
weights = np.zeros(3)
lr = 0.1

for epoch in range(1000):
    z = X_with_bias @ weights
    predictions = sigmoid(z)
    error = predictions - y
    gradient = (1/n) * X_with_bias.T @ error
    weights -= lr * gradient
    
    if (epoch+1) % 200 == 0:
        loss = -np.mean(y * np.log(predictions+1e-15) + 
                       (1-y) * np.log(1-predictions+1e-15))
        print(f"Epoch {epoch+1}: loss={loss:.4f}")

# 预测与评估
z_pred = X_with_bias @ weights
y_pred = (sigmoid(z_pred) >= 0.5).astype(int)
accuracy = np.mean(y_pred == y)
print(f"\n准确率: {accuracy:.4f}")  # 0.965

📊 混淆矩阵与分类指标

# 混淆矩阵计算
tp = np.sum((y_pred == 1) & (y == 1))  # 真阳性
tn = np.sum((y_pred == 0) & (y == 0))  # 真阴性
fp = np.sum((y_pred == 1) & (y == 0))  # 假阳性
fn = np.sum((y_pred == 0) & (y == 1))  # 假阴性

precision = tp / (tp + fp)     # 精确率
recall = tp / (tp + fn)        # 召回率
f1 = 2*precision*recall / (precision+recall)  # F1

print(f"TP={tp}, FP={fp}, FN={fn}, TN={tn}")
print(f"精确率: {precision:.4f}")  # 0.9697
print(f"召回率: {recall:.4f}")     # 0.9600
print(f"F1分数: {f1:.4f}")        # 0.9648
混淆矩阵: 预测正(1) 预测负(0) ─────────── ─────────── 实际正(1) │ TP=96 FN=4 │ 召回率=96/100=96% 实际负(0) │ FP=3 TN=97 │ 特异度=97/100=97% ─────────── ─────────── 精确率=96.9% NPV=96% 准确率 = (96+97)/200 = 96.5% F1 = 2×96.97%×96%/(96.97%+96%) = 96.48%

多分类指标对比

指标公式侧重适用场景
准确率(Accuracy)(TP+TN)/N整体正确类别均衡
精确率(Precision)TP/(TP+FP)少误报垃圾邮件、医疗诊断
召回率(Recall)TP/(TP+FN)少漏报癌症筛查、欺诈检测
F1分数2PR/(P+R)平衡P和R通用分类评估
AUC-ROC曲线下面积排序能力不均衡数据

📈 ROC曲线与AUC

ROC曲线绘制不同阈值下的TPR(召回率) vs FPR,AUC衡量分类器的整体排序能力。

# 手动绘制ROC曲线数据
thresholds = np.linspace(0, 1, 100)
tpr_list, fpr_list = [], []

prob_pos = sigmoid(X_with_bias @ weights)

for thresh in thresholds:
    y_t = (prob_pos >= thresh).astype(int)
    tp_t = np.sum((y_t == 1) & (y == 1))
    fp_t = np.sum((y_t == 1) & (y == 0))
    fn_t = np.sum((y_t == 0) & (y == 1))
    tn_t = np.sum((y_t == 0) & (y == 0))
    tpr_list.append(tp_t / (tp_t + fn_t) if (tp_t + fn_t) > 0 else 0)
    fpr_list.append(fp_t / (fp_t + tn_t) if (fp_t + tn_t) > 0 else 0)

# AUC计算(梯形法)
auc = np.trapz(tpr_list, fpr_list)
print(f"AUC: {auc:.4f}")  # ≈0.99
AUC=1.0表示完美分类器,AUC=0.5等于随机猜测。一般AUC>0.8被认为有实用价值,>0.9是优秀分类器。

🔬 多分类逻辑回归

# Softmax多分类(One-vs-Rest策略)
def softmax(z):
    """Softmax: 将多个输出转化为概率分布"""
    e_z = np.exp(z - np.max(z, axis=1, keepdims=True))  # 数值稳定
    return e_z / e_z.sum(axis=1, keepdims=True)

# 交叉熵损失
def cross_entropy_loss(probs, y_onehot):
    return -np.mean(np.sum(y_onehot * np.log(probs + 1e-15), axis=1))

# 3类分类
np.random.seed(42)
n3 = 300
X3 = np.vstack([
    np.random.normal([0, 0], 1, (100, 2)),
    np.random.normal([3, 3], 1, (100, 2)),
    np.random.normal([6, 0], 1, (100, 2))
])
y3 = np.array([0]*100 + [1]*100 + [2]*100)

# One-hot编码
n_classes = 3
y_onehot = np.eye(n_classes)[y3]

# 训练
X3_bias = np.c_[np.ones(n3), X3]
W = np.zeros((3, n3))
W = np.zeros((3, X3_bias.shape[1]))

for epoch in range(500):
    logits = X3_bias @ W.T
    probs = softmax(logits)
    gradient = (probs - y_onehot).T @ X3_bias / n3
    W -= 0.1 * gradient

y3_pred = softmax(X3_bias @ W.T).argmax(axis=1)
print(f"多分类准确率: {np.mean(y3_pred == y3):.4f}")

📐 2024-2025 逻辑回归前沿

⚖️ 类别不均衡处理

方法原理优缺点
过采样(SMOTE)合成少数类样本✅简单 ❌可能过拟合
欠采样随机删除多数类✅快速 ❌丢失信息
类别权重损失函数加权✅不改变数据 ❌权重难调
Focal Loss降低易样本权重✅自动调节 ❌超参敏感
阈值调整不用0.5默认阈值✅简单有效 ❌需业务配合
# 类别权重调整
def weighted_logistic_regression(X, y, class_weight={0: 1, 1: 5}, lr=0.1, epochs=1000):
    n = len(y)
    weights = np.zeros(X.shape[1])
    sample_weights = np.array([class_weight[yi] for yi in y])
    
    for epoch in range(epochs):
        z = X @ weights
        pred = sigmoid(z)
        error = pred - y
        gradient = (X.T @ (error * sample_weights)) / n
        weights -= lr * gradient
    return weights
🏆 成就解锁:分类准确率>80%
手写逻辑回归在二分类数据上达到 96.5% 准确率,精确率96.97%,召回率96%,F1=96.48%!
Python验证通过 — 逻辑回归准确率: 96.5%(远超80%目标);混淆矩阵: TP=96, FP=3, FN=4, TN=97;精确率0.9697,召回率0.9600,F1=0.9648;交叉熵损失从0.693降至0.095。
思考题:
1. 逻辑回归叫"回归"却是分类算法,为什么?
2. 如果数据完全线性可分,逻辑回归会出现什么问题?
3. 为什么交叉熵损失比MSE更适合分类问题?
4. 类别不均衡时,准确率为什么不再是好指标?

📝 课后练习

  1. 实现L2正则化的逻辑回归,对比正则化效果
  2. 用逻辑回归实现多分类(鸢尾花数据集),One-vs-Rest策略
  3. 实现SMOTE过采样算法,在信用卡欺诈数据上对比效果
  4. 手绘ROC曲线,计算AUC,与sklearn对比
  5. 实现逻辑回归的随机梯度下降版本
📚 参考资料:
• Applied Logistic Regression (Hosmer et al., 2013)
• Pattern Recognition and Machine Learning (Bishop, 2006)
• Focal Loss for Dense Object Detection (Lin et al., 2017)
• sklearn.linear_model.LogisticRegression 官方文档