逻辑回归
目标读者: 机器学习初学者 核心内容: Sigmoid 函数、交叉熵损失、梯度推导、决策边界、Softmax 前置知识: 线性回归、概率统计
1. 从线性回归到逻辑回归
线性回归输出连续值:
但分类问题需要输出概率(0~1 之间)。
解决方案:加一个 Sigmoid 函数把输出压缩到 (0, 1)
2. Sigmoid 函数
2.1 函数特性
| 输入 | 输出 |
|---|---|
2.2 导数(很优雅)
推导过程:
2.3 逻辑回归预测公式
3. 损失函数:交叉熵
3.1 为什么不能用 MSE?
Sigmoid + MSE 会导致:
- 非凸优化:多个局部最小值,梯度下降可能卡住
- 梯度消失:当预测很自信但错误时(如 , ),MSE 的梯度很小
3.2 二分类交叉熵 (Binary Cross-Entropy)
直观理解:
| 真实值 | 预测值 | 损失 | 说明 |
|---|---|---|---|
| 1 | 0.9 | 0.105 | 预测正确,损失小 |
| 1 | 0.1 | 2.303 | 预测错误,损失大 |
| 0 | 0.1 | 0.105 | 预测正确,损失小 |
| 0 | 0.9 | 2.303 | 预测错误,损失大 |
核心思想:预测错得越离谱,惩罚越大!
3.3 交叉熵的概率解释
从最大似然估计角度,假设数据独立同分布:
取负对数(最小化负对数似然 = 最大化似然):
这正是交叉熵损失的形式!
4. 梯度推导
设 ,
4.1 链式法则
4.2 各项计算
第一项:
第二项(Sigmoid 导数):
第三项:
4.3 合并结果
化简:
4.4 最终梯度(与线性回归形式相同!)
向量形式:
这个优雅的结果意味着:梯度下降的代码几乎和线性回归一样,只是预测函数不同。
5. 决策边界
5.1 阈值分类
通过阈值 0.5 进行分类:
- 预测为类别 1
- 预测为类别 0
5.2 决策边界方程
由于 ,决策边界就是:
这是一个线性超平面,所以逻辑回归是线性分类器。
5.3 几何直观
x2
│ 类别 1
│ ● ● ●
│ ● ● ●
─────┼─────────── ← 决策边界 w₁x₁ + w₂x₂ + b = 0
│ ○ ○ ○
│ ○ ○ ○
│ 类别 0
└──────────→ x1
6. 多分类:Softmax
6.1 Softmax 函数
将 K 个类别的得分转换为概率分布:
其中
6.2 性质
- 所有类别概率之和为 1:
- 每个概率在 (0, 1) 之间
- 保持相对大小关系
6.3 多分类交叉熵
如果使用 one-hot 编码(只有真实类别 处 ):
7. 与线性回归对比
| 方面 | 线性回归 | 逻辑回归 |
|---|---|---|
| 任务类型 | 回归 | 分类 |
| 输出范围 | ||
| 激活函数 | 无 | Sigmoid |
| 损失函数 | MSE | 交叉熵 |
| 梯度形式 | ||
| 决策边界 | - | 线性超平面 |
| 输出含义 | 数值预测 | 概率预测 |
8. Scikit-learn 实践
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
# 准备数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 训练模型
model = LogisticRegression()
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test) # 类别预测
y_prob = model.predict_proba(X_test) # 概率预测
# 评估
print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
print(classification_report(y_test, y_pred))
# 查看模型参数
print(f"权重: {model.coef_}")
print(f"偏置: {model.intercept_}")8.1 正则化选项
# L2 正则化(默认)
model_l2 = LogisticRegression(penalty='l2', C=1.0)
# L1 正则化
model_l1 = LogisticRegression(penalty='l1', solver='saga', C=1.0)
# 无正则化
model_none = LogisticRegression(penalty='none')注:C 是正则化强度的倒数,C 越小,正则化越强。
9. 从零实现
import numpy as np
class LogisticRegressionScratch:
def __init__(self, lr=0.01, epochs=1000):
self.lr = lr
self.epochs = epochs
def sigmoid(self, z):
return 1 / (1 + np.exp(-z))
def fit(self, X, y):
m, n = X.shape
self.w = np.zeros(n)
self.b = 0
for _ in range(self.epochs):
z = X @ self.w + self.b
y_hat = self.sigmoid(z)
# 梯度
dw = (1/m) * X.T @ (y_hat - y)
db = (1/m) * np.sum(y_hat - y)
# 更新
self.w -= self.lr * dw
self.b -= self.lr * db
def predict_proba(self, X):
return self.sigmoid(X @ self.w + self.b)
def predict(self, X, threshold=0.5):
return (self.predict_proba(X) >= threshold).astype(int)小结
| 概念 | 要点 |
|---|---|
| Sigmoid | ,将输出压缩到 (0,1) |
| 交叉熵 | ,预测错误惩罚大 |
| 梯度 | 与线性回归形式相同: |
| 决策边界 | ,线性分类器 |
| Softmax | 多分类扩展, |
| 为什么用交叉熵 | 避免 MSE 的非凸和梯度消失问题 |
参考资料
- 吴恩达机器学习 - 逻辑回归
- StatQuest - Logistic Regression
- 《统计学习方法》第 6 章
- 《机器学习》周志华 - 第 3 章