qinghuan
← 机器学习与统计推断 / 全部笔记

单元 10 / 机器学习与统计推断

P0 · 必会主线L1 · 基础

泛化、偏差方差与正则化

先比较训练数据和新数据上的误差,再用一维 Ridge 看参数惩罚怎样改变拟合结果、偏差和方差。

本篇目录 · 按需要跳转

读完这篇,你能做什么

能推导带未惩罚截距的一维 Ridge 解,并用小型重复抽样实验验证经验偏差方差分解。

学习理由、准备要求与知识点

为什么学它

训练损失下降,新数据上却可能变差。是否增加正则化惩罚,要根据数据和评估结果决定。

先读这些内容

知识点清单

  • 经验风险与新数据误差
  • 欠拟合与过拟合
  • 偏差方差和噪声
  • L2参数惩罚
  • Ridge闭式解
  • 截距是否惩罚
  • 特征尺度与正则强度
  • 验证集选择正则系数

运行前先确认Java 17;Python 3.14 标准库 CPU 实验;Ridge 源码基线为 scikit-learn 1.7.2。人工数据闭式拟合与重复抽样无需安装第三方依赖,不使用 GPU 或真实任务数据。

01先弄懂它是什么

模型在练习题上做得好,不代表换一批题还会做。训练误差看的是用来调整参数的那批数据;泛化误差看的是目标场景里的新数据。模型太灵活,可能连偶然噪声都记下来,这叫过拟合;模型太简单,可能连稳定规律都学不出来,这叫欠拟合。不能只按参数多少下结论,还要一起看数据量、噪声、模型偏好的规律和实际评估表现。

可以想象反复换一批训练数据,每次重新训练,再让模型回答同一个测试问题。如果这些预测的平均值偏离了该输入对应的真实平均结果,就体现为偏差;如果各次预测差别很大,就体现为方差。在相应假设下,平方误差可分为偏差平方、预测方差和数据本身无法消除的噪声。不过现实里一次训练只有一个结果,不能据此精确算出这几部分的总体大小。

正则化在拟合目标或模型流程中加入偏好。L2 惩罚倾向较小系数,L1 可促使部分系数为零,早停和数据增强也会改变实际学习过程。本篇集中讨论 Ridge:最小化 sum((y_i-w*x_i-b)^2)+alpha*w^2,alpha 非负,截距 b 不惩罚。这个明确目标决定后面的公式和实验。

文中这几个词,先认一认

经验风险
模型在手头这批训练样本上的平均损失或总损失。
归纳偏好
多种规律都能解释训练数据时,模型或训练方法更倾向选择哪一种。例如更倾向简单、平滑的规律。
Ridge
拟合直线时,除了让预测尽量接近样本,还按设定强度把系数的平方加进要压低的总损失,系数越大,这一项越重。本篇只惩罚斜率 w,不惩罚截距 b;这种做法称为岭回归。

还有陌生词?到术语小抄里看一个具体例子 ↗

02看看它怎么工作

先对截距求最优条件,可得 b=mean(y)-w*mean(x)。把数据中心化为 dx_i=x_i-mean(x)、dy_i=y_i-mean(y),目标中只剩 w,令导数为零得到 w=sum(dx_i*dy_i)/(sum(dx_i^2)+alpha)。这说明正则化通过增大分母收缩斜率,而截距跟随均值重新定位。

用 x=[-1,0,1]、y=2x+1 可以直接看出惩罚的影响:中心化平方和为二、交叉和为四。alpha=0 时 w=2、b=1;alpha=2 时 w=1、b=1。加入惩罚后,训练误差变大了,但在带噪的小数据中,换一批训练数据得到的参数可能不再波动得那么厉害。这是在接受一定偏差的同时争取较小方差,最后是否更好,仍要看目标场景的新数据。

如果 alpha 为零且所有 x 相同,中心化平方和为零,斜率不可唯一辨认。本篇明确拒绝这一情况;alpha 大于零时,惩罚选择 w=0,截距为目标均值。得到一个唯一参数值并不意味着新增了数据中不存在的信息,而是由先验式的优化偏好补足选择。

系数惩罚对特征单位敏感。把 x 从米改成毫米,为保持同一预测需要把 w 缩小一千倍,w^2 惩罚也随之改变。因此比较正则强度时应先明确特征缩放,且缩放统计只在训练集拟合。alpha 对总误差与平均误差目标的含义也不同,换了归约分母就要重新对应系数。

CPU 实验会反复生成带独立噪声的训练集,每份都算一次闭式解,再让模型预测同一个固定输入,观察这些预测怎样波动。这里可验证经验 MSE 等于经验偏差平方加经验预测方差;为了让这个代数关系成立,方差分母使用重复次数本身。它帮助理解各部分怎样组成误差,不表示有限次重复已经精确测出了真实任务的全部泛化误差。

先跑通一个最小例子

只需 Python 3.14 标准库,保存为 experiment.py 后运行 python experiment.py。固定种子生成 2048 份三点数据,每份独立计算闭式解,再核对经验分解;无需训练框架。

experiment.py · python
import math,random,statistics
rng=random.Random(2026)
x=[-1.,0.,1.]
clean=[2*v+1 for v in x]
def fit(y,alpha):
    mean=statistics.fmean(y)
    slope=math.fsum((yi-mean)*xi for xi,yi in zip(x,y))/(2+alpha)
    return slope,mean  # 本组 x 均值为零,截距等于目标均值。
w,b=fit(clean,0)
assert math.isclose(w,2)
assert math.isclose(b,1)
assert math.isclose(fit(clean,2)[0],1)
predictions=[]; shrink=True
for _ in range(2048):
    sample=[v+2*rng.gauss(0,1) for v in clean]
    w0,b0=fit(sample,0); w1,b1=fit(sample,1)
    shrink=shrink and abs(w1)<=abs(w0)+1e-12
    predictions.append(w1+b1)
assert shrink
mean=statistics.fmean(predictions)
bias2=(mean-3)**2
variance=statistics.pvariance(predictions)  # 经验恒等式使用总体分母。
mse=statistics.fmean((v-3)**2 for v in predictions)
assert math.isclose(mse,bias2+variance,abs_tol=1e-12)
assert all(math.isfinite(v) for v in predictions)
print("PASS 6; empirical_mse =",round(mse,6),"bias2 =",round(bias2,6),"variance =",round(variance,6))

核对运行结果打印 PASS 6;系数收缩,经验 MSE 与经验偏差平方加方差一致。具体统计值只对应固定人工数据生成机制。

正在加载流程图…

正则化改变参数分布,验证集用于选择方案,测试集保留给确定后的流程。
查看流程图源码(Mermaid)
flowchart LR
 A["同一数据生成机制重复抽样"] --> B["不同正则强度拟合"]
 B --> C["固定测试点收集预测"]
 C --> D["平均预测与波动"]
 D --> E["偏差方差和误差比较"]

按顺序看,每一步做了什么

  1. 写清损失是总和还是平均。
  2. 明确哪些参数接受惩罚。
  3. 中心化后推导斜率与截距。
  4. 比较不同训练集下的预测分布。
  5. 用独立验证选择系数并记录数据假设。

03对照实现代码

scikit-learn 1.7.2:Ridge 正规方程中的对角惩罚 (新标签页)↗

scikit-learn 1.7.2;sklearn/linear_model/_ridge.py · _solve_cholesky

以下为原创精简教学实现,不是原样库源码;只演示本文说明的机制,省略真实实现的优化、调度和完整兼容边界。

核心机制代码 · python
def centered_ridge(dx,dy,alpha):
    if alpha<0 or len(dx)!=len(dy):
        raise ValueError("input")
    covariance=sum(a*b for a,b in zip(dx,dy))
    denominator=sum(a*a for a in dx)+alpha  # 一维中向对角线加 alpha 退化为分母修正。
    if denominator==0:
        raise ValueError("unidentified slope")
    return covariance/denominator
    # 调用者先中心化;此模型没有实现多维 Cholesky 求解。

scikit-learn 1.7.2 的 _solve_cholesky 先计算 X.T*X 和 X.T*y,然后给前者对角线加 alpha,再调用线性方程求解器。数学上对应 (X^T X+alpha I)w=X^T y,源码使用 solve,并没有简单调用显式矩阵逆来实现注释中的代数形式。

多输出目标可以使用相同或不同的 alpha。源码对统一惩罚和逐目标惩罚有不同分支,并在逐目标处理时恢复对角修正。它展示了公式相同但实现需要管理状态的细节,不能把在循环中不断叠加 alpha 的错误当成每次独立求解。

中心化与截距处理位于更外层的数据准备流程,不能只看这个内部函数就推断它自动识别哪列是截距。本篇明确先中心化,并只惩罚斜率;如果把常数一列也放进受惩罚矩阵,得到的是另一个目标。

原创一维模型只保留对角修正对应分母增加的机制,不实现稀疏输入、多目标或数值分解。真实框架还有其他求解器和适用条件,尤其在秩不足或病态数据中,求解策略会影响稳定性。用闭式小例子核对机制,比把一个内部函数当作全套 Ridge API 更准确。

代码先调用谁,再调用谁

  1. 外层处理样本、权重和截距
  2. 构造 X^T X 与 X^T y
  3. 给受惩罚系数对应对角线加 alpha
  4. 调用稳定线性求解
  5. 恢复截距并形成预测

04动手写一个例子

带未惩罚截距的一维 Ridge

对有限非空样本拟合 sum squared error + alpha*w^2,返回斜率和截距。alpha 非负且有限;无惩罚的常量特征视为斜率不可辨认。

输入 1
x=[-1,0,1],y=[-1,1,3],alpha=0
输出 1
w=2,b=1
输入 2
同样输入 alpha=2
输出 2
w=1,b=1

先求两个均值,再累计中心化交叉和与平方和。把截距解析消去,可以直接看到正则项作用于斜率,而不是同时把整体均值拉向零。算法不修改输入数组,所有统计都在局部变量中完成。

分母是非负平方和加 alpha;只有两者都为零时无法按本契约确定斜率。此时抛错比悄悄做零除或随意选择参数更清楚。alpha 为正且特征常量时,分子为零、分母为正,得到惩罚偏好的零斜率。

对巨大有限输入,中间平方或协方差仍可能越界,所以结果前要检查有限性。数学推导与浮点实现之间存在精度边界;算法用于一维教学参考,不是替代大型数值线性代数库。测试包含无惩罚、收缩、常量特征和非法惩罚等情况。

为什么这样写是对的第二遍结束时,两个累加器分别为中心化交叉和与中心化平方和,截距由最优均值关系恢复。

时间 O(n)。额外空间 O(1) 额外空间。

两次样本扫描加常数次标量求解;只拟合一个斜率与一个截距。

保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。

Main.java · 完整可运行程序 · Java
public class Main {
  record Model(double w,double b){}
  static Model fit(double[] x,double[] y,double alpha){
    if(x==null||y==null||x.length==0||x.length!=y.length||!Double.isFinite(alpha)||alpha<0)throw new IllegalArgumentException("input");
    double mx=0,my=0;
    for(int i=0;i<x.length;i++){
      if(!Double.isFinite(x[i])||!Double.isFinite(y[i]))throw new IllegalArgumentException("finite");
      mx+=x[i]/x.length;my+=y[i]/y.length; // 先除样本数,减少直接总和溢出的机会。
    }
    double xx=0,xy=0;
    for(int i=0;i<x.length;i++){double dx=x[i]-mx,dy=y[i]-my;xx+=dx*dx;xy+=dx*dy;}
    double denominator=xx+alpha; // 正则项只加在斜率方程上。
    if(denominator==0)throw new IllegalArgumentException("unidentified slope");
    double w=xy/denominator,b=my-w*mx; // 截距不受惩罚,恢复目标均值关系。
    if(!Double.isFinite(denominator)||!Double.isFinite(xy)||!Double.isFinite(w)||!Double.isFinite(b))throw new ArithmeticException("range");
    return new Model(w,b);
  }
  static void near(double a,double b){if(!Double.isFinite(a)||Math.abs(a-b)>1e-12)throw new AssertionError();}
  static void bad(Runnable r){try{r.run();}catch(IllegalArgumentException e){return;}throw new AssertionError();}
  public static void main(String[] args){
    double[] x={-1,0,1},y={-1,1,3};
    Model plain=fit(x,y,0);near(plain.w,2);near(plain.b,1);
    Model ridge=fit(x,y,2);near(ridge.w,1);near(ridge.b,1);
    Model constant=fit(new double[]{3,3},new double[]{2,4},1);near(constant.w,0);near(constant.b,3);
    bad(()->fit(new double[]{3,3},new double[]{2,4},0));
    bad(()->fit(x,y,-1));
    bad(()->fit(new double[]{Double.NaN},new double[]{1},1));
    System.out.println("PASS 6");
  }
}

这些特殊情况也要试一试

  • 截距不惩罚是明确选择。
  • alpha=0 与常量特征不可辨认。
  • 正惩罚不能补充不存在的观测信息。
  • 有限输入也可能产生越界中间统计。
进阶选读 · 多维正则化与有效自由度

场景特征高度相关且数量接近或超过样本数。

做法用矩阵分解分析奇异方向的收缩,比较 Ridge、Lasso 与早停,并通过嵌套验证选择超参数。

复杂度求解成本依 n、d 与稀疏性变化;不能由一维 O(n) 直接推广。

好处与代价更强约束可能稳定估计,也可能压掉重要信号,需任务验证而非只看系数变小。

05项目里怎么用

选择正则强度时,不应把测试集当作搜索目标。用训练集拟合候选模型,在验证集比较,最后对确定的流程做独立评估。候选次数越多,选择偏差越值得关注;记录搜索范围和评价指标,才能解释最终模型的形成过程。

特征缩放、损失归约和样本权重都会改变 alpha 的实际意义。跨实现复现时,要先对应目标函数是否除以 n、截距是否受罚、特征是否中心化,而不是仅复制同一个数值。数学名称相同不保证默认设置相同。

正则化不能修复数据泄漏、错误标签或不适用的评估目标。若训练和验证都有共享副本,再强的惩罚也可能给出虚假的好分数。应先建立可信数据边界,再讨论复杂度和泛化;小型人工实验只验证收缩机制与经验分解,不代表真实任务收益。

容易踩的坑

  • 训练误差越低就认为泛化越好。
  • 把单次预测误差当作总体偏差方差。
  • 改变特征单位却保持惩罚含义不变。
  • 不说明截距是否正则化。

几种做法,怎么选

表格有四列,窄屏可左右滑动查看代价和适用条件。

方案优势代价与限制适用条件
无惩罚最小二乘在合适条件下拟合偏差小可能对噪声和共线性敏感数据充分且问题稳定
Ridge连续收缩、改善病态方向增加偏差且不自动稀疏相关特征与小样本
L1或结构约束可强调稀疏和领域结构优化与选择行为更复杂有明确结构需求

06检验是否读懂了

先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。

先用自己的话解释

01正则化为何可能增加训练误差?

展开参考答案与推导

目标同时考虑拟合与参数惩罚,最优点不再只追求训练残差最小。增加的偏差可能换来较小估计波动,但是否改善新数据需要验证。

02alpha 的数值能跨实现直接比较吗?

展开参考答案与推导

不能默认。损失求和或平均、特征缩放、截距和样本权重都会改变它的相对强度,需要先对齐完整目标函数。

03Ridge 选出唯一参数意味着数据足够吗?

展开参考答案与推导

不一定。正惩罚可以在欠定方向选择特定解,这是优化偏好提供的约束,不等于观测数据已经唯一识别真实参数。

换个情况,还会处理吗

01惩罚越大验证误差越高应如何判断?

展开参考答案与推导

可能已进入偏差过大的区域,也可能尺度或数据边界有问题。检查目标定义和验证过程,比较多个适当强度,不应预设更强约束必然更好。

02参数很小但预测仍很差说明什么?

展开参考答案与推导

小参数只是惩罚偏好,并非正确性的保证。模型可能表达能力不足、特征无信息或目标有误,需结合残差与新数据表现诊断。

03每次换训练集预测都变很多怎么办?

展开参考答案与推导

在可信切分下评估方差来源,考虑增加数据、约束模型或正则化,并检查噪声和共线性。不要只挑一次结果好看的训练集报告。

写代码试一试

01求一维收缩解。

输入 / 条件
Sxy=4,Sxx=2,alpha=2
输出 / 预期
w=1

提示 分母加入惩罚。

展开参考答案与推导

斜率为四除以二加二,得到一。若目标均值为一且特征均值为零,未惩罚截距仍为一。

02处理常量特征。

输入 / 条件
所有x相同,alpha=0
输出 / 预期
斜率不可唯一辨认

提示 中心化平方和为零。

展开参考答案与推导

不能用零除或随便返回一个值冒称唯一最小二乘参数。本篇明确拒绝;若选择其他约定,需说明等价预测与参数非唯一性。

03核对经验分解。

输入 / 条件
固定测试目标t,多个预测z
输出 / 预期
mean((z-t)^2)=var_population(z)+(mean(z)-t)^2

提示 使用同一批预测。

展开参考答案与推导

展开平方并利用中心化偏差和为零即可得到恒等式;这里方差分母用重复次数,不是无偏样本方差的次数减一。

读完之后,独立完成

课后作业:自己做一遍

本篇共 10 道作业,先完成 8 道基础与综合任务,再按前置知识挑战进阶题。其中包含 1 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。

这次练什么

能推导带未惩罚截距的一维 Ridge 解,并用小型重复抽样实验验证经验偏差方差分解。

本篇重点加练

正则系数只有结合目标函数和模型选择流程才有意义,重点检验它们的可比性。

  • L2参数惩罚
  • 验证集选择正则系数

重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。

先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。

基础必做

  1. 作业 01原理问答

    为欠拟合、过拟合和噪声上限分别设计可能的训练/验证曲线形态,并解释仅凭单条训练曲线能否区分这三者。

    提交内容
    曲线草图与判断边界
    怎样算完成
    • 现象与成因不混用
    • 替代解释被考虑

    练到的知识点经验风险与新数据误差 · 欠拟合与过拟合 · 偏差方差和噪声

  2. 作业 02代码推演

    设 X=[[1,0],[1,1],[1,2]]、y=[1,2,2],比较截距参与与不参与 L2 惩罚的目标函数与驻点条件。

    提交内容
    目标及方程推导
    怎样算完成
    • 截距约定明确
    • 正则系数与损失缩放一致

    练到的知识点L2参数惩罚 · Ridge闭式解 · 截距是否惩罚

  3. 作业 03原理问答

    两份实现分别最小化 SSE+λ||w||² 和 SSE/n+α||w||²。推导它们描述同一优化问题所需的系数关系,并列出前提。

    提交内容
    目标对照与等价条件
    怎样算完成
    • 样本数与归约完整
    • 惩罚参数集合一致

    练到的知识点L2参数惩罚

综合应用

  1. 作业 04编程实践

    在含噪声的 30 点多项式数据上实现 Ridge,预先固定候选正则系数与验证划分;绘制训练和验证误差并保存最终选择记录。

    提交内容
    CPU 程序与选型日志
    怎样算完成
    • 候选在结果前固定
    • 测试数据不参与选择

    练到的知识点L2参数惩罚 · Ridge闭式解 · 验证集选择正则系数

  2. 作业 05排错实验

    对带非零目标均值的数据比较三种处理:原尺度、特征重标度、错误惩罚截距。保持数据和切分相同,记录参数及预测差异。

    提交内容
    受控实验与差异表
    怎样算完成
    • 只改变声明因素
    • 参数大小与预测质量分开

    练到的知识点截距是否惩罚 · 特征尺度与正则强度

  3. 作业 06面试场景

    一个方法平均验证误差较低但不同训练样本下波动很大。拟定重复训练实验,说明如何报告稳定性及采用方法的条件。

    提交内容
    抽样协议与报告模板
    怎样算完成
    • 重复单位明确
    • 平均与波动同时呈现

    练到的知识点经验风险与新数据误差 · 偏差方差和噪声 · 验证集选择正则系数

  4. 作业 07编程实践

    在固定 24 条二维数据上实现两种损失归约的 Ridge 选型,按自己推导的系数对应关系比较参数与验证排序;故意取消对应关系作为故障对照。

    提交内容
    CPU 代码与完整路径表
    怎样算完成
    • 参数与验证排序分别核对
    • 候选目标在结果前固定

    练到的知识点L2参数惩罚 · 验证集选择正则系数

  5. 作业 08设计评审

    同一验证集被反复用于调整特征、阶数和正则系数。设计实验登记表,说明哪类额外证据才能支持最终泛化声明。

    提交内容
    选择历史与最终评估方案
    怎样算完成
    • 所有选择自由度有记录
    • 未知泛化保持未知

    练到的知识点验证集选择正则系数

进阶挑战 · 掌握前置后选做

  1. 作业 09设计评审

    构造高度共线的双特征数据,评估参数可辨识性、预测稳定性与正则化的关系;加入分布外输入观察并限制结论范围。

    提交内容
    数据生成器与评估报告
    怎样算完成
    • 训练内外评价分开
    • 共线性条件可复现

    练到的知识点偏差方差和噪声 · Ridge闭式解 · 特征尺度与正则强度

思维拓展

先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。

  1. 作业 10思维拓展 · 反例构造

    反驳或限定“增大正则系数一定改善泛化”:构造可在 CPU 上穷举的小型数据生成机制,先固定模型选择协议,再展示支持你论证的结果。

    提交内容
    生成器、预定协议及反例或边界
    怎样算完成
    • 真分布与有限样本分开
    • 不事后只挑一条有利曲线

    练到的知识点L2参数惩罚 · 验证集选择正则系数

完成后,再检验一次

给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。

继续阅读

先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。

打开资料库,找下一份学习材料 ↗