第 6 章 · 03 偏差方差 本节摘要:本节讲机器学习核心理论——偏差方差权衡(Bias-Variance Tradeoff),它是理解欠拟合和过拟合的根本框架。任何模型的期望误差都能分解成三部分:偏差²(模型容量不够,系统性偏离真值)、方差(模型对训练样本过于敏感,换一组数据就大变)、不可约噪声(数据本身的随机性)。本节用多项式拟合 sin 函数做演示:1 次多项式欠拟合(高偏差)、15 次过拟合(高方差)、5 次刚好;再用学习曲线诊断:训练和验证误差都收敛到高位=欠拟合,两者有大间隙=过拟合。理解这套理论,你才能在第 7 章用 Ridge/Lasso 正则化找到「刚刚好」的模型复杂度。 内容来源:原项目 ,汉化并套用体系化模板。 ⚠️ 学习提示:金融数据信噪比极低,极易过拟合。
本节摘要:本节讲机器学习核心理论——偏差方差权衡(Bias-Variance Tradeoff),它是理解欠拟合和过拟合的根本框架。任何模型的期望误差都能分解成三部分:偏差²(模型容量不够,系统性偏离真值)、方差(模型对训练样本过于敏感,换一组数据就大变)、不可约噪声(数据本身的随机性)。本节用多项式拟合 sin 函数做演示:1 次多项式欠拟合(高偏差)、15 次过拟合(高方差)、5 次刚好;再用学习曲线诊断:训练和验证误差都收敛到高位=欠拟合,两者有大间隙=过拟合。理解这套理论,你才能在第 7 章用 Ridge/Lasso 正则化找到「刚刚好」的模型复杂度。
内容来源:原项目
ch06/03_bias_variance.ipynb,汉化并套用体系化模板。
⚠️ 学习提示:金融数据信噪比极低,极易过拟合。偏差方差权衡是金融 ML 最重要的诊断框架——任何「样本内 R² 极高、样本外崩盘」的模型都是高方差。
阅读完本节,你应当能够:
给定真函数 f 和训练集 D,模型 g_D 的期望误差(在测试点 x)可分解为:
经典的「打靶」类比:靶心是真值,每次打靶是一个训练集训练出的模型预测。
| 模型 | 靶上分布 | 解读 |
|---|---|---|
| 低偏差低方差 | 紧密围绕靶心 | 理想,但难达 |
| 高偏差低方差 | 偏离靶心但密集 | 欠拟合,系统偏 |
| 低偏差高方差 | 围绕靶心但散乱 | 过拟合,不稳 |
| 高偏差高方差 | 偏离且散乱 | 模型选错 |
notebook 用 sin 函数 + 噪声生成数据,用 1/5/15 次多项式拟合:
import numpy as np from numpy.random import choice, normal x = np.linspace(-0.5 * np.pi, 2.5 * np.pi, 1000) true_function = pd.Series(np.sin(x), index=x) n, noise = 30, 0.2 x_ = np.random.choice(x, size=n) y_ = np.sin(x_) + normal(loc=0, scale=np.std(y_) * noise, size=n) degrees = [1, 5, 15] for degree in degrees: fit = np.poly1d(np.polyfit(x=x_, y=y_, deg=degree))
三张子图直观对比:
为了数值化偏差和方差,notebook 重复 100 次实验:每次抽一组样本、训练三个复杂度的模型、记录预测。然后统计:
from collections import defaultdict from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error datasets = ['Train', 'Test'] X = {'Train': np.linspace(-1, 1, 1000), 'Test': np.linspace(1, 2, 500)} models = {'Underfit': 1, 'Right Fit': 5, 'Overfit': 9} sample, noise = 25, 0.01 result = [] for i in range(100): x_ = {d: choice(X[d], size=sample, replace=False) for d in datasets} y_ = {d: f(x_[d], max_degree=5) for d in datasets} y_['Train'] += normal(loc=0, scale=np.std(y_['Train']) * noise, size=sample) trained = {fit: np.poly1d(np.polyfit(x=x_['Train'], y=y_['Train'], deg=deg)) for fit, deg in models.items()} for fit, model in trained.items(): for dataset in datasets: pred = model(x_[dataset]) result.append(pd.DataFrame(dict(x=x_[dataset], Model=fit, Data=dataset, y=pred, Error=pred - y_[dataset]))) result = pd.concat(result)
boxplot 显示:
学习曲线(learning curve)横轴是训练样本量,纵轴是训练/验证误差。它能区分两种问题:
notebook 的实现:
def folds(train, test, nfolds): shuffle(train); shuffle(test) steps = (np.array([len(train), len(test)]) / nfolds).astype(int) for fold in range(nfolds): i, j = fold * steps yield train[i:i+steps[0]], test[j:j+steps[1]] def create_poly_data(data, degree): return np.hstack((data.reshape(-1, 1) ** i) for i in range(degree + 1)) # 对每个模型复杂度,扫不同训练样本量,记录 train/test RMSE for label, degree in models.items(): for train_idx in sample_sizes: train_rmse, test_rmse = [], [] for x_train, x_test in folds(train, test, 5): lr.fit(X=x_train, y=f(x_train[:, 1])) train_rmse.append(rmse(y=f(x_train[:, 1]), x=x_train, model=lr)) test_rmse.append(rmse(y=f(x_test[:, 1]), x=x_test, model=lr))
💡 诊断口诀:高偏差看天花板,高方差看间隙。训练误差高天花板=欠拟合;训练验证有大间隙=过拟合。
金融数据有两个特征让它极易过拟合:
后果:任何高容量模型(深度网络、上万棵树)在金融上都可能样本内 R² = 0.5、样本外 R² < 0。对策:
下一节,我们讲时序交叉验证——金融 ML 杜绝数据泄露的灵魂工具,MultipleTimeSeriesCV。