机器学习之线性回归(七)
文章目录
- 机器学习之线性回归(七)
- 一、线性回归
- 线性回归超全指南:从"一条直线"到"正则化调参"的完整旅程
-
- [0. 先对齐语言:标称型 vs 连续型](#0. 先对齐语言:标称型 vs 连续型)
- [1. 问题形式化](#1. 问题形式化)
- [2. 损失函数全景](#2. 损失函数全景)
- [3. 求解方法 1:最小二乘(Normal Equation)](#3. 求解方法 1:最小二乘(Normal Equation))
-
- [3.1 推导](#3.1 推导)
- [3.2 代码](#3.2 代码)
- [4. 求解方法 2:梯度下降家族](#4. 求解方法 2:梯度下降家族)
-
- [4.1 统一更新公式](#4.1 统一更新公式)
- [4.2 自己写 SGD(单变量示例)](#4.2 自己写 SGD(单变量示例))
- [4.3 sklearn 一键调用](#4.3 sklearn 一键调用)
- [5. 特征工程三板斧](#5. 特征工程三板斧)
- [6. 正则化:专治过拟合](#6. 正则化:专治过拟合)
-
- [6.1 目标函数](#6.1 目标函数)
- [6.2 调参模板(GridSearchCV)](#6.2 调参模板(GridSearchCV))
- [7. 实战:完整 Pipeline](#7. 实战:完整 Pipeline)
- [8. 面试 8 连击](#8. 面试 8 连击)
- [9. 可视化:一条直线的前世今生](#9. 可视化:一条直线的前世今生)
- [10. 总结脑图(文字版)](#10. 总结脑图(文字版))
一、线性回归
线性回归超全指南:从"一条直线"到"正则化调参"的完整旅程
面向:想彻底吃透线性回归、并能在面试/竞赛/生产中直接落地的同学
代码:可直接复制运行,覆盖最小二乘、批量/随机/小批量梯度下降、Ridge/Lasso、特征工程、调参模板
0. 先对齐语言:标称型 vs 连续型
类型 | 举例 | 能否做加减 | 机器学习任务 |
---|---|---|---|
标称型 Nominal | 颜色{红, 绿, 蓝}、性别{男, 女} | ❌ | 分类 |
连续型 Continuous | 温度 23.7 ℃、房价 512.3 万 | ✅ | 回归 |
线性回归只处理连续型目标变量 y。
1. 问题形式化
给定数据集 D = { ( x ( i ) , y ( i ) ) } i = 1 m \mathcal{D} = \{(\mathbf{x}^{(i)}, y^{(i)})\}_{i=1}^{m} D={(x(i),y(i))}i=1m,其中
- x ( i ) ∈ R n \mathbf{x}^{(i)} \in \mathbb{R}^n x(i)∈Rn(一行 n n n 个特征)
- y ( i ) ∈ R y^{(i)} \in \mathbb{R} y(i)∈R
我们希望学到一个函数
y ^ = f ( x ) = w ⊤ x + b \hat{y}=f(\mathbf{x})=\mathbf{w}^\top\mathbf{x}+b y^=f(x)=w⊤x+b
使得预测误差最小。为了写矩阵方便,把 b b b 吸收进 w \mathbf{w} w:
y ^ = X w \hat{\mathbf{y}} = X\mathbf{w} y^=Xw
其中
- X ∈ R m × ( n + 1 ) X\in\mathbb{R}^{m\times (n+1)} X∈Rm×(n+1):最后一列全 1,把偏置 b b b 当做 w 0 w_0 w0
- w ∈ R n + 1 \mathbf{w}\in\mathbb{R}^{n+1} w∈Rn+1:待求参数
2. 损失函数全景
名称 | 公式 | 特点 | 场景 |
---|---|---|---|
MSE (L2) | 1 m ∣ y − X w ∣ 2 2 \frac{1}{m}|\mathbf{y}-X\mathbf{w}|_2^2 m1∣y−Xw∣22 | 光滑、可导 | 默认 |
MAE (L1) | 1 m ∣ y − X w ∣ 1 \frac{1}{m}|\mathbf{y}-X\mathbf{w}|_1 m1∣y−Xw∣1 | 对异常值鲁棒 | 数据脏 |
Huber | 混合 L1/L2 | 鲁棒+光滑 | 竞赛 |
Quantile | ... | 预测分位数 | 金融风控 |
下文默认 MSE,因为闭式解 + 凸函数 + 可微。
3. 求解方法 1:最小二乘(Normal Equation)
3.1 推导
对 MSE 求导并令导数为 0:
∇ w Loss = − 2 X ⊤ ( y − X w ) = 0 ⇒ X ⊤ X w = X ⊤ y \nabla_{\mathbf{w}}\text{Loss}= -2X^\top(\mathbf{y}-X\mathbf{w})=0 \Rightarrow X^\top X\mathbf{w}=X^\top\mathbf{y} ∇wLoss=−2X⊤(y−Xw)=0⇒X⊤Xw=X⊤y
若 X ⊤ X X^\top X X⊤X 可逆,则
w = ( X ⊤ X ) − 1 X ⊤ y \boxed{\mathbf{w}=(X^\top X)^{-1}X^\top\mathbf{y}} w=(X⊤X)−1X⊤y
时间复杂度: O ( m n 2 + n 3 ) O(mn^2+n^3) O(mn2+n3),特征 n > 1 0 4 n>10^4 n>104 基本跑不动。
3.2 代码
python
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
# 1. 数据
X, y = fetch_california_housing(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 2. 手动最小二乘
X_b = np.c_[np.ones((X_train.shape[0], 1)), X_train] # 加一列 1
w_exact = np.linalg.inv(X_b.T @ X_b) @ X_b.T @ y_train
# 3. 预测
X_test_b = np.c_[np.ones((X_test.shape[0], 1)), X_test]
y_pred = X_test_b @ w_exact
print("MSE (Normal):", mean_squared_error(y_test, y_pred))
4. 求解方法 2:梯度下降家族
4.1 统一更新公式
w t + 1 = w t − η ∇ w Loss \mathbf{w}_{t+1} = \mathbf{w}t - \eta \nabla{\mathbf{w}}\text{Loss} wt+1=wt−η∇wLoss
对 MSE:
∇ w Loss = 2 m X ⊤ ( X w − y ) \nabla_{\mathbf{w}}\text{Loss}= \frac{2}{m}X^\top(X\mathbf{w}-\mathbf{y}) ∇wLoss=m2X⊤(Xw−y)
算法 | 每次梯度计算量 | 更新频率 | 优点 | 缺点 |
---|---|---|---|---|
BGD | 全量 m m m 条 | 1 epoch/次 | 稳定 | 慢 |
SGD | 1 条 | m m m epoch/次 | 快、可在线 | 噪声大 |
MBGD | b b b 条(batch) | ⌈ m / b ⌉ \lceil m/b\rceil ⌈m/b⌉ epoch/次 | 折中 | 需调 batch |
梯度下降图解:
4.2 自己写 SGD(单变量示例)
python
def sgd_linreg(X, y, lr=0.01, epochs=100, batch_size=32):
m, n = X.shape
X = np.c_[np.ones(m), X] # 加偏置
w = np.random.randn(n + 1)
for epoch in range(epochs):
idx = np.random.permutation(m)
for i in range(0, m, batch_size):
sl = idx[i:i+batch_size]
grad = 2/len(sl) * X[sl].T @ (X[sl] @ w - y[sl])
w -= lr * grad
return w
4.3 sklearn 一键调用
python
from sklearn.linear_model import SGDRegressor
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
sgd = SGDRegressor(
loss='squared_error',
penalty='l2', # Ridge
alpha=1e-4, # 正则强度 λ
learning_rate='adaptive',
eta0=0.01,
max_iter=1000,
random_state=42)
sgd.fit(X_train_s, y_train)
print("MSE (SGD):", mean_squared_error(y_test, sgd.predict(X_test_s)))
5. 特征工程三板斧
-
标准化 :梯度下降必须!
StandardScaler
或RobustScaler
(对异常值稳)。 -
多项式特征 :线性不可分时升维
pythonfrom sklearn.preprocessing import PolynomialFeatures poly = PolynomialFeatures(degree=2, include_bias=False) X_poly = poly.fit_transform(X)
-
离散特征编码:One-Hot 后当作数值即可。
6. 正则化:专治过拟合
6.1 目标函数
- Ridge (L2) :
Loss = 1 2 m ∥ y − X w ∥ 2 2 + λ ∥ w ∥ 2 2 \text{Loss}= \frac{1}{2m}\|\mathbf{y}-X\mathbf{w}\|_2^2 + \lambda\|\mathbf{w}\|_2^2 Loss=2m1∥y−Xw∥22+λ∥w∥22 - Lasso (L1) :
Loss = 1 2 m ∥ y − X w ∥ 2 2 + λ ∥ w ∥ 1 \text{Loss}= \frac{1}{2m}\|\mathbf{y}-X\mathbf{w}\|_2^2 + \lambda\|\mathbf{w}\|_1 Loss=2m1∥y−Xw∥22+λ∥w∥1 - Elastic Net:L1 + L2 的加权组合。
6.2 调参模板(GridSearchCV)
python
from sklearn.model_selection import GridSearchCV
from sklearn.linear_model import RidgeCV, LassoCV
alphas = np.logspace(-3, 3, 20)
ridge = RidgeCV(alphas=alphas, cv=5)
ridge.fit(X_train_s, y_train)
print("Best α Ridge:", ridge.alpha_)
7. 实战:完整 Pipeline
python
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import Ridge
pipe = Pipeline([
('scaler', StandardScaler()),
('poly', PolynomialFeatures(degree=2, include_bias=False)),
('reg', Ridge(alpha=1.0))
])
pipe.fit(X_train, y_train)
print("Test MSE:", mean_squared_error(y_test, pipe.predict(X_test)))
8. 面试 8 连击
- 最小二乘一定可逆吗?
不一定,需 X ⊤ X X^\top X X⊤X 满秩;不可逆时用伪逆或加 λ I \lambda I λI(Ridge)。 - MSE vs MAE 对异常值?
MSE 平方放大异常值;MAE 线性增长。 - 梯度下降为什么会震荡?
学习率过大 or 特征未标准化。 - L1 为什么能做特征选择?
解空间为菱形,最优解易落在顶点 → 某些权重=0。 - Ridge 与 Lasso 何时选?
高维+稀疏 → Lasso;特征相关性强 → Ridge。 - 多项式升维后还是线性回归吗?
对 参数 仍线性,对 特征 非线性。 - SGD 如何选 batch_size?
小数据 32~256;GPU 训练可 1024+。 - 如何监控收敛?
画loss vs epoch
曲线;早停(Early Stopping)。
9. 可视化:一条直线的前世今生
python
import matplotlib.pyplot as plt
plt.scatter(X_train[:,0], y_train, s=5)
plt.plot(X_test[:,0], ridge.predict(X_test), 'r')
plt.title("Ridge Regression on California Housing")
plt.show()
10. 总结脑图(文字版)
数据 → 清洗/标准化 → 特征工程(多项式/离散化)
↓
选模型
├─ 最小二乘(闭式解) ------ 小数据、可解释
├─ 梯度下降家族 ------ 大数据、在线学习
│ ├─ BGD(全量)
│ ├─ MBGD(batch)
│ └─ SGD(单条)
└─ 正则化
├─ Ridge(L2)
├─ Lasso(L1)
└─ Elastic Net
↓
评估(MSE/R²/MAE) → 调参(α, degree, batch, lr) → 上线