第 16.5 篇:防止过拟合的公式原理——为什么这些方法真的有效

在第十六篇里,我们已经从直觉上理解了:

过拟合,本质是模型把训练数据学得太细了,
细到连噪声都当成规律。

然后我们介绍了几类常见方法:

  • 限制模型复杂度
  • 正则化
  • 剪枝
  • 早停
  • 增加数据
  • 特征选择
  • 随机化方法

如果只停在直觉层面,其实已经够用了。
但如果你想真正理解:

为什么这些方法能减少过拟合

那就需要稍微看一点数学结构。

你会发现一件很有意思的事:

这些看起来不同的方法,本质上都在控制同一件事:模型复杂度。

而“复杂度”在数学上,往往通过:

  • 参数大小
  • 参数数量
  • 函数形状
  • 模型自由度

来体现。


1. 先回忆一下模型在优化什么

几乎所有监督学习模型,都在做一件事:

最小化损失函数:

Loss=1n∑i=1nL(yi,y^i) Loss = \frac{1}{n}\sum_{i=1}^{n} L(y_i, \hat{y}_i) Loss=n1i=1nL(yi,y^i)

例如:

回归常用平方误差:

L=1n∑(yi−y^i)2 L = \frac{1}{n}\sum (y_i - \hat{y}_i)^2 L=n1(yiy^i)2

分类常用交叉熵:

L=−1n∑yilog⁡(y^i) L = -\frac{1}{n}\sum y_i \log(\hat{y}_i) L=n1yilog(y^i)

问题在于:

如果你只最小化训练误差,模型可能会越来越复杂,直到把训练数据“记住”。

这时,虽然训练误差很低,但泛化能力下降。

所以我们需要给优化目标加一点“约束”。


2. 正则化:给模型一个“别太复杂”的惩罚项

最经典的方法,就是在损失函数中增加一个复杂度惩罚项:

Loss=原始损失+λ⋅正则项 Loss = 原始损失 + \lambda \cdot 正则项 Loss=原始损失+λ正则项

这里的 λ 控制惩罚强度。

λ 越大,对复杂模型的惩罚越强。

λ 越小,模型越自由。

这就是正则化的核心思想。


3. L2 正则化(Ridge)

L2 正则化会惩罚参数过大:

Loss=1n∑(yi−y^i)2+λ∑wj2 Loss = \frac{1}{n}\sum (y_i - \hat{y}_i)^2 + \lambda \sum w_j^2 Loss=n1(yiy^i)2+λwj2

这里:

∑wj2 \sum w_j^2 wj2

表示所有参数平方的和。

它的作用是:

如果某些参数变得非常大,Loss 会变大。

因此优化过程会倾向于:

让参数保持较小数值。


为什么参数大容易过拟合

当某些权重特别大时,模型会对某些特征极端敏感。

例如线性模型:

y^=w1x1+w2x2 \hat{y} = w_1 x_1 + w_2 x_2 y^=w1x1+w2x2

如果:

w₁ = 1000

模型对 x₁ 的微小变化都会产生巨大输出变化。

这通常意味着:

模型在贴训练集细节。

而不是学习稳定规律。

L2 正则化会让权重分布更平滑:

每个特征贡献适中。

不容易过拟合某个局部特征。


4. L1 正则化(Lasso)

L1 正则化惩罚参数绝对值:

Loss=原始损失+λ∑∣wj∣ Loss = 原始损失 + \lambda \sum |w_j| Loss=原始损失+λwj

与 L2 不同的是:

L1 更容易让某些参数变成 0。

这意味着:

模型会自动忽略部分特征。

因此 L1 不仅防止过拟合,还能:

降低特征维度。

这也是为什么 L1 经常用于:

特征选择。


5. 为什么正则化能减少方差

从偏差-方差角度看:

加入正则化以后:

模型自由度降低。

这意味着:

模型不再随意调整参数去贴训练数据。

结果通常是:

偏差略微增加
方差明显下降

总体泛化误差下降。

这就是正则化的意义。


6. 决策树剪枝的数学直觉

决策树的目标通常是最小化:

节点纯度指标。

例如 Gini 指数:

Gini=1−∑pk2 Gini = 1 - \sum p_k^2 Gini=1pk2

或信息熵:

Entropy=−∑pklog⁡pk Entropy = -\sum p_k \log p_k Entropy=pklogpk

树越深:

节点越纯。

训练误差越低。

但问题是:

深层节点往往样本很少。

例如某个叶子节点只有 2 个样本:

纯度当然是 100%。

但这种纯度并不可靠。

它只是记住了训练样本。

剪枝的本质是:

不要允许节点划分得太细。

即:

不要让模型用极少样本去定义规则。

这可以看成:

限制模型自由度。


7. 早停的数学意义

很多模型通过迭代优化:

例如梯度下降:

wt+1=wt−η∇Loss w_{t+1} = w_t - \eta \nabla Loss wt+1=wtηLoss

在训练初期:

模型先学习主要规律。

随着迭代继续:

模型开始拟合训练集噪声。

训练误差:

持续下降。

但泛化误差:

可能开始上升。

早停的做法是:

在验证误差最小时停止训练。

这相当于:

限制模型继续增加复杂度。

因此早停也可以看作:

一种隐式正则化。


8. 随机森林为什么能减少过拟合

随机森林使用 Bagging:

对数据进行重复采样:

D1,D2,D3...DB D_1, D_2, D_3 ... D_B D1,D2,D3...DB

每个数据集训练一棵树:

f1(x),f2(x),...,fB(x) f_1(x), f_2(x), ..., f_B(x) f1(x),f2(x),...,fB(x)

最后预测:

y^=1B∑fb(x) \hat{y} = \frac{1}{B}\sum f_b(x) y^=B1fb(x)

如果每棵树的误差方差为:

σ2 \sigma^2 σ2

平均后的方差:

Var(y^)=σ2B Var(\hat{y}) = \frac{\sigma^2}{B} Var(y^)=Bσ2

即:

树越多,方差越低。

这也是为什么随机森林:

比单棵树更稳定。

更不容易过拟合。


9. GBDT 为什么需要学习率

GBDT 每一步更新:

Fm(x)=Fm−1(x)+ηhm(x) F_m(x) = F_{m-1}(x) + \eta h_m(x) Fm(x)=Fm1(x)+ηhm(x)

η 是学习率。

如果 η 太大:

每棵树修正太多。

容易过拟合。

如果 η 较小:

每棵树只做微调。

模型变化更平滑。

泛化能力更好。

因此学习率控制:

模型拟合速度。

也控制复杂度增长速度。


10. SVM 正则化项

SVM 的目标函数:

min⁡12∣∣w∣∣2+C∑ξi \min \frac{1}{2}||w||^2 + C\sum \xi_i min21∣∣w2+Cξi

第一项:

∣∣w∣∣2 ||w||^2 ∣∣w2

控制模型复杂度。

使间隔最大。

第二项:

∑ξi \sum \xi_i ξi

控制分类误差。

参数 C 决定:

更重视误差
还是更重视间隔。

C 越大:

模型越努力拟合训练集。

更容易过拟合。

C 越小:

模型更强调间隔。

泛化更稳。


11. 为什么增加数据可以减少过拟合

设模型误差:

E=Bias2+Variance+Noise E = Bias^2 + Variance + Noise E=Bias2+Variance+Noise

方差项通常与样本数量相关:

Variance∝1n Variance \propto \frac{1}{n} Variancen1

样本越多:

模型对单个样本的依赖越小。

偶然性被平均掉。

因此:

更多数据通常意味着:

更稳定的模型。


12. 特征选择为什么也能防止过拟合

如果特征过多:

模型可能找到一些偶然相关性。

例如:

特征数量 p 远大于样本数量 n:

模型可能总能找到一组参数:

使训练误差很低。

但这些关系未必真实存在。

减少特征数量:

相当于减少模型自由度。

因此降低方差。

减少过拟合。


13. 所有方法其实在控制同一件事

现在你可以把这些方法统一起来看:

方法 控制的东西
L1/L2 参数大小
剪枝 树深
早停 训练步数
随机森林 模型方差
学习率 每步复杂度增长
特征选择 输入维度
更多数据 降低方差

它们形式不同,但本质都是:

限制模型复杂度。


14. 从公式角度理解过拟合

如果模型过于复杂:

训练误差:

↓ \downarrow

方差:

↑ \uparrow

泛化误差:

↑ \uparrow

正则化等方法的作用是:

适度增加训练误差。

降低方差。

最终降低测试误差。

这也是为什么:

训练误差最低的模型,不一定是最好的模型。


15. 这一篇真正想补充的是什么

前面正文讲的是:

直觉理解:

为什么要防过拟合。

这一篇补充的是:

数学结构:

为什么这些方法真的有效。

当你从公式角度看,会发现:

机器学习里很多看起来不同的技巧,其实都在解决同一个问题:

如何限制模型复杂度,使模型更稳定。

一旦理解这一点,你在面对新算法时,也能更快抓住核心。

因为你会下意识去找:

这个方法是如何控制模型复杂度的。

而不是只记它的名字。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐