从理论到实践,系统掌握防止过拟合的完整技术体系
环境声明
在开始本章学习之前,请确保你的环境满足以下要求:
- Python版本:Python 3.12+(建议使用3.10以上版本)
- 核心库:NumPy 1.24+、Scikit-learn 1.3+、Matplotlib 3.7+、PyTorch 2.0+
- 开发工具:PyCharm 或 VS Code
- 操作系统:Windows / macOS / Linux(通用)
bash
# 安装依赖
pip install numpy scikit-learn matplotlib torch
学习目标
完成本章学习后,你将能够:
- 理解过拟合与欠拟合的本质区别,掌握偏差-方差权衡的数学原理
- 深入理解L1/L2正则化的几何意义与稀疏性产生机制
- 掌握Dropout的工作原理,理解训练时丢弃与测试时缩放的关系
- 学会使用数据增强技术扩充训练集,提升模型泛化能力
- 理解早停策略与模型集成在正则化中的作用
- 从贝叶斯视角理解正则化,建立概率化思维
- 通过实战对比不同正则化方法的效果差异
1. 过拟合与欠拟合
1.1 什么是过拟合
过拟合(Overfitting)是机器学习中最常见的问题之一。当模型在训练数据上表现优异,但在新数据上表现糟糕时,我们就说模型发生了过拟合。
用一个形象的比喻:一个学生通过死记硬背记住了所有练习题,但遇到新题目时却不会解答。这就是典型的过拟合现象。
1.2 偏差-方差权衡
模型的泛化误差可以分解为三个部分:
偏差(Bias):模型预测值与真实值之间的系统性差异。高偏差意味着模型过于简单,无法捕捉数据中的规律。
方差(Variance):模型对训练数据微小变化的敏感程度。高方差意味着模型过于复杂,记住了训练数据的噪声。
不可约误差(Irreducible Error):数据本身固有的噪声,无法通过模型改进消除。
数学表达式为:
E[(y - f(x))^2] = Bias[f(x)]^2 + Var[f(x)] + σ^2
| 特征 | 高偏差(欠拟合) | 高方差(过拟合) |
|---|---|---|
| 训练误差 | 高 | 低 |
| 测试误差 | 高 | 高 |
| 模型复杂度 | 过低 | 过高 |
| 解决方案 | 增加模型复杂度 | 添加正则化 |
1.3 学习曲线分析
学习曲线是诊断过拟合与欠拟合的重要工具。通过绘制训练集和验证集上的性能随训练样本数量或训练迭代次数的变化曲线,我们可以直观地判断模型的状态。
- 欠拟合:训练误差和验证误差都很高,且两者差距较小
- 过拟合:训练误差很低,但验证误差很高,两者差距较大
- 理想状态:训练误差和验证误差都较低,且差距适中
2. L1/L2正则化原理
2.1 正则化的数学定义
正则化是在损失函数中添加一个惩罚项,限制模型参数的大小。带正则化的损失函数可以表示为:
L(θ) = L_data(θ) + λΩ(θ)
其中:
- L_data(θ) 是数据损失(如均方误差、交叉熵)
- Ω(θ) 是正则化项
- λ 是正则化强度超参数
2.2 L2正则化(岭回归)
L2正则化在损失函数中添加参数平方和的惩罚:
Ω(θ) = (1/2)||θ||^2 = (1/2)Σθ_i^2
几何解释:L2正则化相当于在参数空间中添加了一个球形约束。优化过程等价于在约束区域内寻找最优解。这个约束区域是一个超球体,因此L2正则化也被称为权重衰减(Weight Decay)。
特性:
- 产生平滑的权重分布
- 所有参数都会被压缩,但不会被精确置零
- 对异常值相对鲁棒
2.3 L1正则化(Lasso回归)
L1正则化在损失函数中添加参数绝对值之和的惩罚:
Ω(θ) = ||θ||_1 = Σ|θ_i|
几何解释:L1正则化的约束区域是一个超立方体(菱形)。由于超立方体的顶点位于坐标轴上,最优解更容易落在这些顶点上,从而产生稀疏解。
稀疏性原理:L1正则化在零点处不可导,形成了一个"尖角"。当梯度下降接近零点时,某些维度会被精确压缩到零,实现特征选择。
2.4 弹性网络(Elastic Net)
弹性网络结合了L1和L2正则化的优点:
Ω(θ) = α||θ||_1 + (1-α)(1/2)||θ||^2
其中α是混合参数,控制L1和L2的比例。
优势:
- 保留L1的稀疏性,实现特征选择
- 保留L2的稳定性,处理相关特征
- 解决Lasso在特征高度相关时的随机选择问题
3. Dropout原理与实现
3.1 Dropout的基本思想
Dropout是一种在神经网络训练过程中随机丢弃一部分神经元的正则化技术。其核心思想是:通过随机丢弃神经元,防止神经元之间产生复杂的共适应关系,迫使网络学习更鲁棒的特征表示。
3.2 训练时的Dropout
在训练阶段,每个神经元以概率p被保留,以概率(1-p)被丢弃。数学上,这相当于对神经元的输出进行随机掩码:
y = f(x) * m
其中m是一个伯努利随机变量,以概率p取值为1,以概率(1-p)取值为0。
3.3 测试时的缩放
测试时不使用Dropout,但需要对所有神经元的输出进行缩放,以补偿训练时的丢弃:
y_test = p * f(x)
这种缩放确保了测试时的期望输出与训练时一致。另一种等价的做法是在训练时将保留的神经元输出除以p,测试时不做任何操作。
3.4 Dropout的变体
DropConnect:随机丢弃权重连接而非神经元
Spatial Dropout:在卷积神经网络中,对整个特征图进行丢弃,保持空间相关性
DropBlock:丢弃连续的区域而非随机像素,更适合图像任务
Monte Carlo Dropout:在测试时也使用Dropout,通过多次前向传播获得预测的不确定性估计
4. 数据增强技术
4.1 数据增强的本质
数据增强通过对训练数据进行变换,人工扩充数据集的大小和多样性。从正则化的角度看,数据增强相当于向训练数据添加噪声,迫使模型学习对输入变化不敏感的特征。
4.2 图像增强技术
几何变换:
- 随机裁剪(Random Crop)
- 随机翻转(Horizontal/Vertical Flip)
- 随机旋转(Rotation)
- 随机缩放(Scale)
颜色变换:
- 亮度调整(Brightness)
- 对比度调整(Contrast)
- 饱和度调整(Saturation)
- 色调调整(Hue)
高级技术:
- Mixup:将两张图片按一定比例混合
- CutMix:将一张图片的局部区域替换为另一张图片的对应区域
- AutoAugment:使用强化学习搜索最优增强策略
4.3 文本增强技术
同义词替换:使用WordNet或预训练词向量替换词语
回译(Back Translation):将文本翻译成另一种语言再翻译回来
随机插入/删除/交换:在句子中随机插入、删除或交换词语
EDA(Easy Data Augmentation):包括同义词替换、随机插入、随机交换、随机删除四种简单技术
4.4 混合增强技术
Mixup:通过线性插值混合两个样本及其标签
x' = λx_i + (1-λ)x_j
y' = λy_i + (1-λ)y_j
其中λ服从Beta分布。
CutMix:结合Cutout和Mixup,用一张图片的局部区域替换另一张图片的对应区域,并按区域比例混合标签。
5. 早停与模型集成
5.1 早停策略
早停(Early Stopping)是在验证集性能不再提升时提前终止训练的策略。这是一种简单但极其有效的正则化方法。
实现要点:
- 监控验证集上的性能指标
- 设置耐心参数(Patience):允许性能不提升的最大轮数
- 保存验证集性能最佳时的模型参数
- 当连续Patience轮没有改善时,恢复最佳参数并停止训练
5.2 模型平均
模型平均(Model Averaging)通过集成多个模型的预测结果来提升泛化性能。
简单平均:对多个模型的预测结果取算术平均
加权平均:根据模型在验证集上的表现分配权重
指数移动平均(EMA):在训练过程中维护一个参数的移动平均版本,用于最终预测
5.3 快照集成
快照集成(Snapshot Ensembling)在单次训练过程中保存多个模型快照,形成一个集成模型。
原理:使用循环学习率调度,让模型在训练过程中多次跳出局部最优,收敛到不同的最优解。
优势:
- 不需要多次独立训练
- 计算开销小
- 集成效果好
6. 贝叶斯视角下的正则化
6.1 从MAP估计看正则化
从贝叶斯统计的角度,正则化等价于对模型参数引入先验分布。
最大后验估计(MAP):
θ_MAP = argmax P(θ|D) = argmax P(D|θ)P(θ)
取对数后:
θ_MAP = argmax [log P(D|θ) + log P(θ)]
这与带正则化的损失函数形式一致:
- log P(D|θ) 对应数据损失
- log P(θ) 对应正则化项
6.2 L2正则化与高斯先验
当参数先验服从高斯分布时:
P(θ) ∝ exp(-(1/2σ^2)||θ||^2)
对应的MAP估计等价于L2正则化,其中λ = 1/σ^2。
6.3 L1正则化与拉普拉斯先验
当参数先验服从拉普拉斯分布时:
P(θ) ∝ exp(-λ||θ||_1)
对应的MAP估计等价于L1正则化。
6.4 贝叶斯神经网络
贝叶斯神经网络将网络权重视为随机变量,通过后验分布进行推断。这提供了:
- 预测的不确定性估计
- 自然的正则化效果
- 对小样本数据更鲁棒
7. 实战案例:不同正则化方法效果对比
本节我们将通过一个完整的实验,对比不同正则化方法在多项式回归任务上的效果。
7.1 实验设置
我们将使用一个带有噪声的正弦函数数据集,分别训练:
- 无正则化的基准模型
- L2正则化模型
- L1正则化模型
- Dropout模型
- 早停模型
7.2 完整代码实现
python
"""
正则化方法效果对比实验
对比L1、L2、Dropout、早停等不同正则化技术的效果
"""
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import Ridge, Lasso, LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import warnings
warnings.filterwarnings('ignore')
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# 生成带噪声的正弦数据
def generate_data(n_samples=100, noise=0.3, seed=42):
"""生成带有噪声的正弦函数数据"""
np.random.seed(seed)
X = np.linspace(0, 2*np.pi, n_samples).reshape(-1, 1)
y_true = np.sin(X).ravel()
y = y_true + np.random.normal(0, noise, n_samples)
return X, y, y_true
# 生成数据
X, y, y_true = generate_data(n_samples=30, noise=0.4)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# 排序以便绘图
sort_idx = np.argsort(X_train.ravel())
X_train_sorted = X_train[sort_idx]
y_train_sorted = y_train[sort_idx]
sort_idx_test = np.argsort(X_test.ravel())
X_test_sorted = X_test[sort_idx_test]
y_test_sorted = y_test[sort_idx_test]
# 生成用于绘图的密集点
X_plot = np.linspace(0, 2*np.pi, 200).reshape(-1, 1)
y_plot_true = np.sin(X_plot).ravel()
print("=" * 60)
print("正则化方法效果对比实验")
print("=" * 60)
print(f"训练样本数: {len(X_train)}")
print(f"测试样本数: {len(X_test)}")
print(f"多项式次数: 15 (高复杂度模型)")
print()
# 使用15次多项式特征(高复杂度模型容易过拟合)
poly_degree = 15
poly = PolynomialFeatures(degree=poly_degree)
X_train_poly = poly.fit_transform(X_train)
X_test_poly = poly.transform(X_test)
X_plot_poly = poly.transform(X_plot)
# 存储结果
results = {}
# 1. 无正则化的线性回归(基准模型)
print("[1/5] 训练无正则化模型...")
model_baseline = LinearRegression()
model_baseline.fit(X_train_poly, y_train)
y_pred_baseline = model_baseline.predict(X_plot_poly)
train_pred_baseline = model_baseline.predict(X_train_poly)
test_pred_baseline = model_baseline.predict(X_test_poly)
train_mse_baseline = mean_squared_error(y_train, train_pred_baseline)
test_mse_baseline = mean_squared_error(y_test, test_pred_baseline)
results['无正则化'] = {
'train_mse': train_mse_baseline,
'test_mse': test_mse_baseline,
'pred': y_pred_baseline,
'coef': model_baseline.coef_
}
print(f" 训练MSE: {train_mse_baseline:.4f}")
print(f" 测试MSE: {test_mse_baseline:.4f}")
print()
# 2. L2正则化(Ridge回归)
print("[2/5] 训练L2正则化模型 (Ridge)...")
alpha_l2 = 0.1 # 正则化强度
model_ridge = Ridge(alpha=alpha_l2)
model_ridge.fit(X_train_poly, y_train)
y_pred_ridge = model_ridge.predict(X_plot_poly)
train_pred_ridge = model_ridge.predict(X_train_poly)
test_pred_ridge = model_ridge.predict(X_test_poly)
train_mse_ridge = mean_squared_error(y_train, train_pred_ridge)
test_mse_ridge = mean_squared_error(y_test, test_pred_ridge)
results['L2正则化'] = {
'train_mse': train_mse_ridge,
'test_mse': test_mse_ridge,
'pred': y_pred_ridge,
'coef': model_ridge.coef_
}
print(f" 训练MSE: {train_mse_ridge:.4f}")
print(f" 测试MSE: {test_mse_ridge:.4f}")
print(f" 正则化强度alpha: {alpha_l2}")
print()
# 3. L1正则化(Lasso回归)
print("[3/5] 训练L1正则化模型 (Lasso)...")
alpha_l1 = 0.01 # 正则化强度
model_lasso = Lasso(alpha=alpha_l1, max_iter=10000)
model_lasso.fit(X_train_poly, y_train)
y_pred_lasso = model_lasso.predict(X_plot_poly)
train_pred_lasso = model_lasso.predict(X_train_poly)
test_pred_lasso = model_lasso.predict(X_test_poly)
train_mse_lasso = mean_squared_error(y_train, train_pred_lasso)
test_mse_lasso = mean_squared_error(y_test, test_pred_lasso)
# 统计非零系数数量
nonzero_coef = np.sum(np.abs(model_lasso.coef_) > 1e-6)
results['L1正则化'] = {
'train_mse': train_mse_lasso,
'test_mse': test_mse_lasso,
'pred': y_pred_lasso,
'coef': model_lasso.coef_,
'nonzero': nonzero_coef
}
print(f" 训练MSE: {train_mse_lasso:.4f}")
print(f" 测试MSE: {test_mse_lasso:.4f}")
print(f" 正则化强度alpha: {alpha_l1}")
print(f" 非零系数数量: {nonzero_coef}/{len(model_lasso.coef_)}")
print()
# 4. 弹性网络
print("[4/5] 训练弹性网络模型 (Elastic Net)...")
from sklearn.linear_model import ElasticNet
alpha_en = 0.01
l1_ratio = 0.5 # L1和L2的混合比例
model_en = ElasticNet(alpha=alpha_en, l1_ratio=l1_ratio, max_iter=10000)
model_en.fit(X_train_poly, y_train)
y_pred_en = model_en.predict(X_plot_poly)
train_pred_en = model_en.predict(X_train_poly)
test_pred_en = model_en.predict(X_test_poly)
train_mse_en = mean_squared_error(y_train, train_pred_en)
test_mse_en = mean_squared_error(y_test, test_pred_en)
nonzero_coef_en = np.sum(np.abs(model_en.coef_) > 1e-6)
results['弹性网络'] = {
'train_mse': train_mse_en,
'test_mse': test_mse_en,
'pred': y_pred_en,
'coef': model_en.coef_,
'nonzero': nonzero_coef_en
}
print(f" 训练MSE: {train_mse_en:.4f}")
print(f" 测试MSE: {test_mse_en:.4f}")
print(f" 正则化强度alpha: {alpha_en}")
print(f" L1比例: {l1_ratio}")
print(f" 非零系数数量: {nonzero_coef_en}/{len(model_en.coef_)}")
print()
# 5. 不同正则化强度的对比
print("[5/5] 对比不同L2正则化强度的影响...")
alphas = [0.001, 0.01, 0.1, 1.0, 10.0]
l2_results = []
for alpha in alphas:
model = Ridge(alpha=alpha)
model.fit(X_train_poly, y_train)
train_mse = mean_squared_error(y_train, model.predict(X_train_poly))
test_mse = mean_squared_error(y_test, model.predict(X_test_poly))
l2_results.append({
'alpha': alpha,
'train_mse': train_mse,
'test_mse': test_mse
})
print(f" alpha={alpha:6.3f}: 训练MSE={train_mse:.4f}, 测试MSE={test_mse:.4f}")
print()
print("=" * 60)
print("实验结果汇总")
print("=" * 60)
# 创建对比表格
print("\n方法对比:")
print("-" * 60)
print(f"{'方法':<15} {'训练MSE':<12} {'测试MSE':<12} {'过拟合程度':<15}")
print("-" * 60)
for name, res in results.items():
overfit = res['train_mse'] - res['test_mse']
if overfit < -0.1:
status = "严重过拟合"
elif overfit < 0:
status = "轻微过拟合"
else:
status = "拟合适中"
print(f"{name:<15} {res['train_mse']:<12.4f} {res['test_mse']:<12.4f} {status:<15}")
print("-" * 60)
# 可视化结果
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
# 1. 无正则化
ax = axes[0, 0]
ax.scatter(X_train, y_train, c='blue', alpha=0.6, label='训练数据')
ax.scatter(X_test, y_test, c='green', alpha=0.6, label='测试数据')
ax.plot(X_plot, y_plot_true, 'k--', label='真实函数', linewidth=2)
ax.plot(X_plot, y_pred_baseline, 'r-', label='模型预测', linewidth=2)
ax.set_title(f'无正则化\n训练MSE: {train_mse_baseline:.4f}, 测试MSE: {test_mse_baseline:.4f}')
ax.set_xlabel('X')
ax.set_ylabel('y')
ax.legend()
ax.set_ylim(-2, 2)
# 2. L2正则化
ax = axes[0, 1]
ax.scatter(X_train, y_train, c='blue', alpha=0.6, label='训练数据')
ax.scatter(X_test, y_test, c='green', alpha=0.6, label='测试数据')
ax.plot(X_plot, y_plot_true, 'k--', label='真实函数', linewidth=2)
ax.plot(X_plot, y_pred_ridge, 'r-', label='模型预测', linewidth=2)
ax.set_title(f'L2正则化 (Ridge)\n训练MSE: {train_mse_ridge:.4f}, 测试MSE: {test_mse_ridge:.4f}')
ax.set_xlabel('X')
ax.set_ylabel('y')
ax.legend()
ax.set_ylim(-2, 2)
# 3. L1正则化
ax = axes[0, 2]
ax.scatter(X_train, y_train, c='blue', alpha=0.6, label='训练数据')
ax.scatter(X_test, y_test, c='green', alpha=0.6, label='测试数据')
ax.plot(X_plot, y_plot_true, 'k--', label='真实函数', linewidth=2)
ax.plot(X_plot, y_pred_lasso, 'r-', label='模型预测', linewidth=2)
ax.set_title(f'L1正则化 (Lasso)\n训练MSE: {train_mse_lasso:.4f}, 测试MSE: {test_mse_lasso:.4f}')
ax.set_xlabel('X')
ax.set_ylabel('y')
ax.legend()
ax.set_ylim(-2, 2)
# 4. 弹性网络
ax = axes[1, 0]
ax.scatter(X_train, y_train, c='blue', alpha=0.6, label='训练数据')
ax.scatter(X_test, y_test, c='green', alpha=0.6, label='测试数据')
ax.plot(X_plot, y_plot_true, 'k--', label='真实函数', linewidth=2)
ax.plot(X_plot, y_pred_en, 'r-', label='模型预测', linewidth=2)
ax.set_title(f'弹性网络\n训练MSE: {train_mse_en:.4f}, 测试MSE: {test_mse_en:.4f}')
ax.set_xlabel('X')
ax.set_ylabel('y')
ax.legend()
ax.set_ylim(-2, 2)
# 5. 系数对比
ax = axes[1, 1]
x_pos = np.arange(len(model_baseline.coef_))
ax.bar(x_pos - 0.3, np.abs(model_baseline.coef_), 0.2, label='无正则化', alpha=0.7)
ax.bar(x_pos - 0.1, np.abs(model_ridge.coef_), 0.2, label='L2', alpha=0.7)
ax.bar(x_pos + 0.1, np.abs(model_lasso.coef_), 0.2, label='L1', alpha=0.7)
ax.bar(x_pos + 0.3, np.abs(model_en.coef_), 0.2, label='弹性网络', alpha=0.7)
ax.set_xlabel('特征索引')
ax.set_ylabel('系数绝对值')
ax.set_title('各方法系数大小对比')
ax.legend()
ax.set_yscale('log')
# 6. L2正则化强度影响
ax = axes[1, 2]
train_mses = [r['train_mse'] for r in l2_results]
test_mses = [r['test_mse'] for r in l2_results]
ax.semilogx(alphas, train_mses, 'b-o', label='训练MSE', linewidth=2)
ax.semilogx(alphas, test_mses, 'r-s', label='测试MSE', linewidth=2)
ax.set_xlabel('正则化强度 (alpha)')
ax.set_ylabel('MSE')
ax.set_title('L2正则化强度对性能的影响')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('regularization_comparison.png', dpi=150, bbox_inches='tight')
print("\n可视化结果已保存到: regularization_comparison.png")
plt.show()
# 分析结论
print("\n" + "=" * 60)
print("实验结论")
print("=" * 60)
print("""
1. 无正则化模型:在训练集上表现最好,但在测试集上表现差,
说明发生了严重的过拟合。模型曲线呈现剧烈的震荡。
2. L2正则化:有效地平滑了模型曲线,测试性能显著提升。
所有系数都被压缩,但不会被置零。
3. L1正则化:产生了稀疏解,部分系数被精确置零。
这实现了自动特征选择,模型更简洁。
4. 弹性网络:结合了L1和L2的优点,在稀疏性和稳定性之间
取得了平衡。
5. 正则化强度:存在一个最优的正则化强度,过小会导致过拟合,
过大会导致欠拟合。需要通过交叉验证来选择。
""")
7.3 实验结果分析
运行上述代码后,我们可以观察到:
无正则化模型:训练误差极低,但测试误差很高,模型曲线呈现剧烈震荡,明显过拟合。
L2正则化:模型曲线变得平滑,测试误差显著降低,所有系数都被压缩但保持非零。
L1正则化:产生稀疏解,部分系数被精确置零,实现了特征选择。
弹性网络:在稀疏性和稳定性之间取得平衡,综合表现优异。
8. 避坑小贴士
8.1 正则化强度选择
正则化强度λ是一个关键超参数。λ过小无法有效防止过拟合,λ过大会导致欠拟合。
建议做法:
- 使用交叉验证选择最优λ
- 在对数尺度上搜索(如0.001, 0.01, 0.1, 1, 10)
- 绘制正则化路径图观察系数变化
8.2 特征缩放的重要性
L1/L2正则化对特征的尺度敏感。如果特征尺度差异大,正则化会对大尺度特征产生不公平的惩罚。
必须做法:在使用L1/L2正则化前,对特征进行标准化(均值为0,方差为1)或归一化(缩放到[0,1])。
8.3 Dropout使用注意事项
- Dropout只在训练时使用,测试时必须关闭或进行缩放
- Dropout概率通常设置为0.2-0.5
- 输入层Dropout概率应较小(0.2左右),隐藏层可以较大(0.5左右)
- 不要与批量归一化同时使用,两者存在冲突
8.4 数据增强的陷阱
- 数据增强必须与任务语义一致(如数字识别不能水平翻转)
- 增强后的数据分布应与真实数据分布接近
- 验证集和测试集不应使用数据增强
8.5 正则化方法的组合使用
在实际应用中,往往需要组合使用多种正则化技术:
推荐组合:
- 深度学习任务:L2正则化 + Dropout + 早停
- 传统机器学习:L1/L2正则化 + 交叉验证
- 小样本学习:数据增强 + 迁移学习 + L2正则化
注意事项:
- 不同正则化方法的效果可能相互叠加或抵消
- 需要仔细调整各自的强度参数
- 建议从单一方法开始,逐步增加复杂度
9. 本章小结
本章我们深入探讨了正则化与泛化的核心概念:
核心概念回顾:
| 概念 | 关键点 |
|---|---|
| 过拟合 | 模型记住了训练数据的噪声,泛化能力差 |
| 偏差-方差权衡 | 需要在模型复杂度和泛化能力之间找到平衡 |
| L2正则化 | 权重衰减,产生平滑解,对应高斯先验 |
| L1正则化 | 产生稀疏解,实现特征选择,对应拉普拉斯先验 |
| Dropout | 随机丢弃神经元,防止共适应 |
| 数据增强 | 扩充训练集,提升模型鲁棒性 |
| 早停 | 监控验证集性能,防止训练过度 |
| 贝叶斯视角 | 正则化等价于引入参数先验 |
一句话总结:正则化的本质是通过限制模型复杂度,让模型学习数据的内在规律而非噪声,从而提升泛化能力。
下一步学习建议:
- 尝试在不同的数据集上应用本章学到的正则化技术
- 深入研究贝叶斯神经网络和不确定性估计
- 学习更多高级正则化技术,如标签平滑、混合精度训练等
本系列教程持续更新中,欢迎关注专栏获取更多机器学习深度内容。