共计 2734 个字符,预计需要花费 7 分钟才能阅读完成。
过拟合与欠拟合的数学本质
1. 核心概念图解
通过二维图表可以直观展示模型表现:
-
过拟合区域(高方差低偏差):训练误差远低于测试误差,模型完美拟合训练数据但泛化能力差。数学上对应模型复杂度过高,$E_{test} \gg E_{train}$
-
欠拟合区域(低方差高偏差):训练误差与测试误差都较高,模型未能捕捉数据规律。数学表现为 $E_{train} \approx E_{test}$ 且两者数值较大

图表说明:横轴为模型复杂度,纵轴为误差值。过拟合出现在右侧高复杂度区域,欠拟合出现在左侧低复杂度区域
2. 方差 - 偏差分解公式
模型总误差可分解为:
$$E = \text{Bias}^2 + \text{Variance} + \text{Irreducible Error}$$
- Bias(偏差):模型预测值与真实值的系统性差异
- Variance(方差):模型对训练数据波动的敏感程度
诊断方法实战
1. 学习曲线绘制代码
import matplotlib.pyplot as plt
from sklearn.model_selection import learning_curve
def plot_learning_curve(estimator, X, y):
train_sizes, train_scores, test_scores = learning_curve(estimator, X, y, cv=5, scoring='neg_mean_squared_error')
plt.figure(figsize=(10,6))
plt.plot(train_sizes, -train_scores.mean(1), 'o-', label='Train')
plt.plot(train_sizes, -test_scores.mean(1), 'o-', label='Test')
# 关键拐点标注(过拟合判断)if (-test_scores.mean(1)[-1] + train_scores.mean(1)[-1]) > 0.2:
plt.axvline(x=train_sizes[np.argmin(test_scores.mean(1))],
linestyle='--', color='red', label='Overfit Point')
plt.legend()
return plt
2. 验证曲线示例
from sklearn.model_selection import validation_curve
def plot_validation_curve(estimator, X, y, param_name, param_range):
train_scores, test_scores = validation_curve(
estimator, X, y,
param_name=param_name,
param_range=param_range,
cv=5, scoring="accuracy"
)
plt.plot(param_range, train_scores.mean(1), 'o-', label='Train')
plt.plot(param_range, test_scores.mean(1), 'o-', label='Test')
plt.xlabel(param_name)
plt.legend()
调参方案精讲
1. 过拟合对策
L2 正则化实现(权重衰减)
import torch.nn as nn
class LinearRegression(nn.Module):
def __init__(self, input_dim, l2_lambda=0.01):
super().__init__()
self.linear = nn.Linear(input_dim, 1)
self.l2_lambda = l2_lambda
def forward(self, x):
return self.linear(x)
def l2_regularization(self):
return self.l2_lambda * torch.sum(self.linear.weight**2)
Dropout 层配置(PyTorch)
model = nn.Sequential(nn.Linear(784, 256),
nn.ReLU(),
nn.Dropout(p=0.5), # 随机丢弃 50% 神经元
nn.Linear(256, 10)
)
2. 欠拟合对策
特征工程 checklist
- [] 检查特征相关性(pearson 系数 >0.3)
- [] 尝试多项式特征(sklearn.preprocessing.PolynomialFeatures)
- [] 添加交叉特征(如
age * income) - [] 检查缺失值处理(均值填充 vs 删除)
模型复杂度提升
- 增加神经网络隐藏层维度
- 使用更复杂的核函数(如 RBF kernel)
- 延长决策树的最大深度
避坑指南
1. 数据泄漏检测
常见错误场景:
- 在标准化处理时使用全量数据(包括测试集)计算均值和方差
- 特征选择时查看测试集性能
- 时间序列数据打乱顺序导致未来信息泄漏
正确做法:
from sklearn.pipeline import Pipeline
pipe = Pipeline([('scaler', StandardScaler()), # 仅用训练数据 fit
('model', LogisticRegression())
])
pipe.fit(X_train, y_train) # 自动隔离处理
2. 时间序列交叉验证
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
# 保证时间顺序不被打乱
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
延伸思考
-
Batch Size 影响:当增大 batch size 时,模型倾向于找到更平坦的最小值(flat minima),理论上会降低过拟合风险,但需要多少训练数据来补偿?
-
早停法矛盾:当使用早停法(early stopping)防止过拟合时,如何避免因验证集划分随机性导致的模型性能波动?
-
正则化协同:L1 和 L2 正则化同时使用时(ElasticNet),两者的比例系数如何影响特征选择效果?
实践建议
关键结论:
– 过拟合时优先尝试 增加正则化强度 或减少模型参数
– 欠拟合应首先检查 特征工程完整性 而非盲目增加复杂度
– 时间序列数据必须使用 专属验证策略
最后建议在实际项目中建立模型性能监控表,定期记录训练 / 测试误差、特征重要性等指标变化趋势。
