Python 现代开发学习笔记

(二十三)过拟合与验证集选择

训练损失衡量模型对参与更新的样本拟合得怎样。把已见样本拟合得更紧,也可能把噪声一起记住,需要用未参与更新的数据继续观察。

# 项目文件:demos/overfit_curve.py
import torch

x = torch.linspace(-1, 1, 9, dtype=torch.float64)
y = x.square() + torch.tensor([0.2, -0.2, 0.15, -0.2, 0.1, 0.2, -0.15, 0.2, -0.2])
val_x = torch.linspace(-0.95, 0.95, 80, dtype=torch.float64)
for degree in [2, 8]:
    design = torch.stack([x**power for power in range(degree + 1)], dim=1)
    weights = torch.linalg.lstsq(design, y).solution
    train_error = ((design @ weights - y) ** 2).mean()
    val_design = torch.stack([val_x**power for power in range(degree + 1)], dim=1)
    val_error = ((val_design @ weights - val_x.square()) ** 2).mean()
    # 同一组训练点拟合得更紧,不代表未参加拟合的点误差更小。
    print(
        "次数",
        degree,
        "训练误差",
        round(train_error.item(), 6),
        "验证误差",
        round(val_error.item(), 6),
    )

这份演示在九个 y=x2y=x^2 的训练点上加入固定扰动,分别拟合二次和八次多项式;另取八十个点检查原来的平方关系。八次多项式可以几乎经过所有带噪训练点,但点与点之间会弯折,验证误差反而更大。

二次曲线平滑近似原关系,八次曲线追着九个噪声点弯折,按同一批未参与拟合的位置比较验证误差

完整项目每轮只比较验证损失,改善时复制一份独立权重,记住对应轮数;训练最后一轮未必就是选中的一轮。测试集在整个选择流程之后单独读取。

可以通过增加合适样本、减小模型、加入正则化或在验证效果不再改善时停止,继续比较同一任务。第一步仍是核对划分、标签和预处理,再根据训练与验证曲线判断问题出在哪一段。

笔记正文与全部题解 · Ctrl / ⌘ K