本节摘要:监督学习的核心矛盾是偏差-方差权衡,所有过拟合对策都在调这个天平。本节从偏差方差分解出发,讲清正则化、交叉验证、集成学习这些贯穿 ML 的思想,再落到 SVM、决策树、GBDT/XGBoost 三大经典算法。这些算法本身在大模型时代用得少了,但它们背后的优化思想——间隔最大化、信息增益、梯度提升——是理解现代深度学习训练技巧的钥匙。理解了 GBDT 的加法模型,再看 ResNet 的残差学习会顺理成章。
阅读完本节,你应当能够:
机器学习入门最容易踩的坑,是把每种算法当成独立的"工具箱"——SVM 是一个箱子、决策树是另一个、神经网络又是一个。这种学法在面试时一问就垮,因为面试官追问的永远是"为什么",而你只背了"是什么"。
真正的理解脉络是这样的:所有监督学习都在解同一个方程——找一个函数 f,让它在训练集上的损失小(拟合),同时在测试集上也小(泛化)。这两者天生矛盾,因为训练集只是真实分布的采样,过度拟合训练集必然在测试集上翻车。这就是偏差-方差权衡。
偏差衡量模型"平均猜得准不准"——偏差高说明模型太简单,连训练集都没学明白(欠拟合)。方差衡量模型"对不同的训练集敏感不敏感"——方差高说明模型太复杂,换个训练集就变样(过拟合)。所有经典算法的设计,本质上都是在用不同方式控制这个权衡:
抓住了这条主线,每个算法都不是孤立的知识点,而是同一思想的不同工程实现。
对于一个测试点 x,模型的期望预测误差可以分解成三部分(假设噪声为零):
其中偏差是模型预测均值与真实值的差,方差是模型在不同训练集上预测的波动,\sigma^2 是数据本身的噪声(不可约)。
💡 关键直觉:偏差和方差此消彼长,不可能同时最小。模型复杂度增加,偏差降但方差升;复杂度降低,方差降但偏差升。正则化、剪枝、dropout 都是在压低方差,代价是稍微抬升偏差。集成学习的妙处在于:Bagging 通过平均多个模型,能在不显著抬升偏差的情况下大幅降方差。
正则化是在损失函数里加一个对参数大小的惩罚项。L1 正则加的是参数绝对值之和,L2 正则加的是参数平方和。两者都能防过拟合,但带来的解的性质截然不同。
| 维度 | L1 正则(Lasso) | L2 正则(Ridge) |
|---|---|---|
| 惩罚项 | \sum \lvert w_i \rvert | \sum w_i^2 |
| 约束区域 | 菱形(L1 球) | 圆形(L2 球) |
| 解的性质 | 稀疏(很多参数为零) | 小而密集 |
| 几何直觉 | 等高线易与菱形顶点相交 | 等高线与圆相切于任意点 |
| 典型应用 | 特征选择 | 权重衰减、防止过拟合 |
L1 的稀疏性来自几何:L1 的约束区域是菱形,菱形的顶点在坐标轴上,损失函数的等高线和菱形相切时,切点大概率落在顶点,对应某些参数严格为零。L2 的约束区域是圆,等高线和圆相切可以在任意方向,参数都非零但都偏小。
💡 关键直觉:L1 相当于拉普拉斯先验(MAP 推导),L2 相当于高斯先验。这条链路把"为什么 L1 稀疏"和"贝叶斯先验"统一了起来——稀疏性不是 L1 的魔法,而是拉普拉斯分布在零点有个尖峰,倾向于把参数推向零。
支持向量机的核心思想不是"找一个超平面分开两类"(这感知机就能做),而是"找让两类间隔最大的那个超平面"。间隔越大,对噪声和新样本的鲁棒性越好。
间隔定义为样本到决策边界的最短距离。最大化间隔等价于最小化 \frac{1}{2}\lVert w \rVert^2,约束是每个样本被正确分类且有足够裕量。这就是一个带约束的二次规划问题。
核函数 是 SVM 的精髓。很多数据在原始空间线性不可分,但映射到高维空间就可分了。核函数 K(x_i, x_j) = \phi(x_i)^T \phi(x_j) 让我们直接计算高维空间的内积,而不用显式构造高维特征。常用核有线性核、多项式核、RBF 核(高斯核)。
软间隔 是工程上的妥协。硬间隔要求所有样本严格分开,对异常值极度敏感——一个离群点就能让超平面大幅偏移。软间隔引入松弛变量 \xi_i,允许个别样本违反间隔,但每个违反要在目标里加惩罚,由参数 C 控制惩罚力度。C 大代表对违反零容忍(容易过拟合),C 小代表宽容(可能欠拟合)。
决策树 用递归二分(或多分)的方式把特征空间切成若干区域,每个区域给一个预测值。关键是怎么选分裂点——不同算法用不同的纯度度量:
决策树单独用容易过拟合(方差高),所以实战几乎都用它的集成版本。
Bagging(Bootstrap Aggregating) 对训练集做有放回采样得到多个子集,每个子集训一棵树,最后投票或平均。随机森林是 Bagging 的代表,它额外加了特征随机选择,让每棵树更"多样"。Bagging 降方差的机理是:多个独立模型的平均,方差降为原来的 1/n(理想独立情况下)。
Boosting 的思路完全不同:串行训练一系列弱学习器,每个新模型专门纠正前一个模型的错误。GBDT 用负梯度作为新模型的拟合目标,本质是把加法模型 F(x) = \sum \rho_m h_m(x) 的参数用梯度下降优化。XGBoost 是 GBDT 的工程化升级,主要改进三点:目标函数二阶泰勒展开(用上一阶和二阶信息)、支持缺失值自动处理、支持特征并行与列采样。
| 维度 | Bagging(随机森林) | Boosting(GBDT/XGBoost) |
|---|---|---|
| 训练方式 | 并行 | 串行 |
| 主要作用 | 降方差 | 降偏差 |
| 基学习器 | 深决策树 | 浅决策树 |
| 对异常值 | 鲁棒 | 敏感 |
| 典型代表 | 随机森林 | XGBoost、LightGBM |
面对一个过拟合的模型,不是无脑加正则,而是按"先数据后模型"的顺序排查。
def diagnose_overfitting(train_score, val_score): gap = train_score - val_score if gap > 0.1: # 训练集明显好于验证集 if train_score < 0.1: return "复杂度过高,开始正则化或减模型" else: return "数据不足或数据泄露,先查数据" elif val_score > 0.2: return "欠拟合,增复杂度或加特征" return "状态正常"
⚠️ 常见坑:很多人发现训练集和验证集差距大就立刻加 dropout 或 L2,但真正的元凶往往是数据泄露——某个特征在训练和预测时"提前知道了答案"(比如用未来信息预测过去)。先查数据,再调模型。
K 折交叉验证是评估模型泛化能力的标准做法,但有几个坑:
from sklearn.model_selection import StratifiedKFold from sklearn.preprocessing import StandardScaler def proper_cv(X, y, model_factory, k=5): skf = StratifiedKFold(n_splits=k, shuffle=True, random_state=42) scores = [] for train_idx, val_idx in skf.split(X, y): # 每折内部独立标准化 scaler = StandardScaler() X_train = scaler.fit_transform(X[train_idx]) X_val = scaler.transform(X[val_idx]) model = model_factory() model.fit(X_train, y[train_idx]) scores.append(model.score(X_val, y[val_idx])) return scores
到 2026 年,大模型在语言和图像上已经全面碾压传统方法,但在结构化表格数据上,XGBoost/LightGBM 仍然是首选。原因有几个:
💡 关键直觉:选模型不是看哪个"先进",而是看数据结构和任务。图像、文本、语音是高维稠密信号,深度学习赢在表示学习;表格是低维稀疏信号,树模型赢在特征处理的天然优势。
| 方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 网格搜索 | 遍历所有组合 | 简单彻底 | 维度灾难 |
| 随机搜索 | 随机采样组合 | 高维下优于网格 | 不保证最优 |
| 贝叶斯优化 | 用代理模型预测下个尝试点 | 样本效率高 | 实现复杂 |
实战中,少量超参数用网格,多超参数用随机搜索或贝叶斯优化(Optuna 是流行工具)。
下一节进入深度学习,看反向传播、CNN、RNN、Transformer 这些积木如何把"特征工程"自动化,并撑起整个现代 AI。
最后补一段实战中处理过拟合的决策顺序,面试里以"你的模型过拟合了怎么办"出现率极高。正确答法不是罗列手段,而是给出排查顺序:先看数据(能否扩充、清洗噪声标签),再看正则(权重衰减、Dropout),再考虑降模型容量,最后才是换架构。这个顺序的逻辑是成本递增——动数据最便宜也最有效,换架构最贵。能说出"先诊断再开药"的候选人,天然带着工程气质。