哈喽,大家好~
之前有同学问到:为什么正则项能抑制过拟合?
咱们今天好好聊聊这个问题~
这其实是很多初学者甚至研究生都会反复绕进去的一个核心疑问:到底是为啥在目标函数里加一个“正则项”就能让模型更稳健,不至于在训练集上玩得花里胡哨,但一到测试集就扑街?
先举一个简单的例子:当你要去考驾照,驾校教练让你做题库练习。你如果死记硬背每一道题的答案,不考虑题目的本质逻辑,那考试的时候只要题干稍微一变,你就懵了。这就叫“过拟合”:你对训练题记忆得太死板,缺乏对规律的理解。
反过来,如果你多总结:“红灯停、绿灯行、黄灯要小心”,这样即使考试题目换了问法,你也能答对。这就类似“正则化”的作用:它迫使你不要一味记答案,而是去掌握更简洁、普遍适用的规律。
在机器学习里,模型如果太“自由”,它会用各种弯弯绕绕把训练数据拟合得特别完美,但这些细节大多数其实是噪声。正则项就是一个“惩罚机制”,强行告诉模型:“别太复杂!保持简单点!”
什么是正则项?
在机器学习或者深度学习里,我们的目标函数通常长这样:
其中:
是普通的损失函数,比如均方误差(MSE)、交叉熵(Cross-Entropy)。 就是正则项,也叫做惩罚项。 是一个权重超参数,用来平衡“拟合数据”和“保持简单”之间的矛盾。
常见的正则项有:
L1 正则(Lasso):,会促使参数稀疏(很多参数直接变 0)。 L2 正则(Ridge):,会让参数尽量小,不会无边界增长。
核心逻辑:为什么正则化能抑制过拟合?
这个问题的核心答案其实可以归结为三个角度:
1. 限制模型的自由度
没有正则项的时候,模型可以随便长出“奇形怪状”的决策边界,训练集拟合得很完美,但泛化性很差。正则化就像一个“拴狗绳”,让模型不要乱跑,只能走相对简单的路径。
2. 降低参数的方差
统计学里有个“偏差-方差分解(Bias-Variance Tradeoff)”。过拟合其实就是“方差太大”。L2 正则化等价于给参数加一个高斯先验,鼓励它们不要乱跳,从而降低方差。
3. 避免对噪声的过度拟合
数据里总有噪声。如果不加限制,模型就会想方设法去“记住噪声”。正则项就像老师提醒你:“别背错题答案,背错了考试就完了。”
从公式角度推一推
以最常见的线性回归为例。
普通线性回归目标函数是:
解出来的参数是:
如果 接近奇异(比如特征高度相关),就会导致解特别不稳定,小小的噪声就能让 巨变 → 过拟合。
加上 L2 正则(Ridge):
推导结果是:
可以看到,原来可能“不可逆”的 ,现在加了 后一定可逆,参数解更稳定。而且因为参数被惩罚得不能太大,所以不会过度拟合噪声。
加上 L1 正则(Lasso):
这里没法直接得到解析解,但 L1 的效果是会让很多 直接变 0,相当于自动帮你做特征选择,只保留最关键的变量,从而减少复杂度。
没有正则 => 模型就是个“老好人”,所有细节都想照顾,最后结果四不像。 L2 正则 => 就像跟你说:“你可以用很多参数,但别太激动,数值都收敛一点,不要暴走。” L1 正则 => 就像教练说:“别瞎用一堆没用的特征,挑重点就好,其他干脆全忽略。”
所以,本质上正则化就是:让模型别太贪心,克制住复杂度,专注于核心规律。
举个具体例子
假设我们用一个高次多项式去拟合一组数据。
如果我们不加正则化,模型可能会长得“像一条蛇”,在每个点附近疯狂震荡,把噪声都拟合进去。训练集误差接近 0,但测试集一塌糊涂。 如果我们加 L2 正则,模型会被迫选择系数较小的多项式,最终是一条比较平滑的曲线。虽然训练误差没那么低,但测试误差显著下降。
这就是正则化的直观好处:牺牲一点训练精度,换来泛化能力。
代码实现
咱们来写个小实验:用多项式回归拟合带噪声的数据,看看正则化的作用。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import make_pipeline
# 生成数据
np.random.seed(42)
X = np.linspace(0, 1, 15)[:, np.newaxis]
y = np.sin(2 * np.pi * X).ravel() + np.random.randn(len(X)) * 0.2 # 加噪声
# 测试集
X_test = np.linspace(0, 1, 100)[:, np.newaxis]
y_true = np.sin(2 * np.pi * X_test).ravel()
# 多项式阶数
degree = 12
# 普通线性回归(高阶多项式拟合)
model_lr = make_pipeline(PolynomialFeatures(degree), LinearRegression())
model_lr.fit(X, y)
# Ridge 正则化
model_ridge = make_pipeline(PolynomialFeatures(degree), Ridge(alpha=1.0))
model_ridge.fit(X, y)
# Lasso 正则化
model_lasso = make_pipeline(PolynomialFeatures(degree), Lasso(alpha=0.01, max_iter=5000))
model_lasso.fit(X, y)
# 绘图
plt.figure(figsize=(12,6))
plt.scatter(X, y, label="训练数据", color="black")
plt.plot(X_test, y_true, label="真实函数 sin(2πx)", linewidth=2)
plt.plot(X_test, model_lr.predict(X_test), label="无正则化 (过拟合)", linestyle="--")
plt.plot(X_test, model_ridge.predict(X_test), label="Ridge 正则化", linestyle="-.")
plt.plot(X_test, model_lasso.predict(X_test), label="Lasso 正则化", linestyle=":")
plt.legend()
plt.title("正则化对过拟合的抑制作用")
plt.show()
运行结果你会发现:
无正则化:曲线在训练点之间疯狂乱跳,过拟合严重。 Ridge:曲线明显更平滑,虽然没做到训练集误差最小,但测试点上表现更好。 Lasso:曲线也比较平滑,并且部分多项式项系数被压成 0,模型变得更简洁。

其实正则项还有一个很漂亮的“贝叶斯解释”。
L2 正则化等价于假设参数 服从一个高斯先验分布 。 L1 正则化等价于假设参数 服从一个拉普拉斯分布 。
换句话说,正则化就是在“硬塞”一个先验信念进去:
我们认为参数大概率不会特别大,或者大多数参数应该为 0。
这在贝叶斯框架下就很自然了:先验 + 似然 → 后验,正则项就是那个先验。
总结
到这里,咱们就能回答最初的问题了:
为什么正则项能抑制过拟合?
因为它限制了模型的复杂度,让模型不至于瞎折腾噪声。 因为它稳定了解,降低了方差,避免参数乱飞。 因为它相当于在模型上加了一个“先验”,提醒模型:别想太复杂,简单才是真的。
在深度学习里,Dropout 其实也可以看作是一种正则化,它通过“随机屏蔽神经元”来降低模型复杂度。
权重衰减(Weight Decay):在深度学习里 L2 正则常常叫 weight decay,就是每次更新参数时让它往 0 收缩一点。
早停(Early Stopping):虽然不是加项,但它的本质也是一种正则化,防止训练太久过拟合。
所以咱么就会发现,整个机器学习里很多技巧本质上就是各种各样的“正则化手段”。
最后

