读完这篇,你能做什么
能推导带未惩罚截距的一维 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 份三点数据,每份独立计算闭式解,再核对经验分解;无需训练框架。
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["偏差方差和误差比较"]按顺序看,每一步做了什么
- 写清损失是总和还是平均。
- 明确哪些参数接受惩罚。
- 中心化后推导斜率与截距。
- 比较不同训练集下的预测分布。
- 用独立验证选择系数并记录数据假设。
03对照实现代码
scikit-learn 1.7.2;sklearn/linear_model/_ridge.py · _solve_cholesky
以下为原创精简教学实现,不是原样库源码;只演示本文说明的机制,省略真实实现的优化、调度和完整兼容边界。
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 更准确。
代码先调用谁,再调用谁
- 外层处理样本、权重和截距
- 构造 X^T X 与 X^T y
- 给受惩罚系数对应对角线加 alpha
- 调用稳定线性求解
- 恢复截距并形成预测
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 为正且特征常量时,分子为零、分母为正,得到惩罚偏好的零斜率。
对巨大有限输入,中间平方或协方差仍可能越界,所以结果前要检查有限性。数学推导与浮点实现之间存在精度边界;算法用于一维教学参考,不是替代大型数值线性代数库。测试包含无惩罚、收缩、常量特征和非法惩罚等情况。
为什么这样写是对的第二遍结束时,两个累加器分别为中心化交叉和与中心化平方和,截距由最优均值关系恢复。
两次样本扫描加常数次标量求解;只拟合一个斜率与一个截距。
保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。
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参数惩罚
- 验证集选择正则系数
重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。
先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。
基础必做
- 作业 01原理问答
为欠拟合、过拟合和噪声上限分别设计可能的训练/验证曲线形态,并解释仅凭单条训练曲线能否区分这三者。
- 提交内容
- 曲线草图与判断边界
- 怎样算完成
- 现象与成因不混用
- 替代解释被考虑
练到的知识点经验风险与新数据误差 · 欠拟合与过拟合 · 偏差方差和噪声
- 作业 02代码推演
设 X=[[1,0],[1,1],[1,2]]、y=[1,2,2],比较截距参与与不参与 L2 惩罚的目标函数与驻点条件。
- 提交内容
- 目标及方程推导
- 怎样算完成
- 截距约定明确
- 正则系数与损失缩放一致
练到的知识点L2参数惩罚 · Ridge闭式解 · 截距是否惩罚
- 作业 03原理问答
两份实现分别最小化 SSE+λ||w||² 和 SSE
/n+α||w||²。推导它们描述同一优化问题所需的系数关系,并列出前提。- 提交内容
- 目标对照与等价条件
- 怎样算完成
- 样本数与归约完整
- 惩罚参数集合一致
练到的知识点L2参数惩罚
综合应用
- 作业 04编程实践
在含噪声的 30 点多项式数据上实现 Ridge,预先固定候选正则系数与验证划分;绘制训练和验证误差并保存最终选择记录。
- 提交内容
- CPU 程序与选型日志
- 怎样算完成
- 候选在结果前固定
- 测试数据不参与选择
练到的知识点L2参数惩罚 · Ridge闭式解 · 验证集选择正则系数
- 作业 05排错实验
对带非零目标均值的数据比较三种处理:原尺度、特征重标度、错误惩罚截距。保持数据和切分相同,记录参数及预测差异。
- 提交内容
- 受控实验与差异表
- 怎样算完成
- 只改变声明因素
- 参数大小与预测质量分开
练到的知识点截距是否惩罚 · 特征尺度与正则强度
- 作业 06面试场景
一个方法平均验证误差较低但不同训练样本下波动很大。拟定重复训练实验,说明如何报告稳定性及采用方法的条件。
- 提交内容
- 抽样协议与报告模板
- 怎样算完成
- 重复单位明确
- 平均与波动同时呈现
练到的知识点经验风险与新数据误差 · 偏差方差和噪声 · 验证集选择正则系数
- 作业 07编程实践
在固定 24 条二维数据上实现两种损失归约的 Ridge 选型,按自己推导的系数对应关系比较参数与验证排序;故意取消对应关系作为故障对照。
- 提交内容
- CPU 代码与完整路径表
- 怎样算完成
- 参数与验证排序分别核对
- 候选目标在结果前固定
练到的知识点L2参数惩罚 · 验证集选择正则系数
- 作业 08设计评审
同一验证集被反复用于调整特征、阶数和正则系数。设计实验登记表,说明哪类额外证据才能支持最终泛化声明。
- 提交内容
- 选择历史与最终评估方案
- 怎样算完成
- 所有选择自由度有记录
- 未知泛化保持未知
练到的知识点验证集选择正则系数
进阶挑战 · 掌握前置后选做
- 作业 09设计评审
构造高度共线的双特征数据,评估参数可辨识性、预测稳定性与正则化的关系;加入分布外输入观察并限制结论范围。
- 提交内容
- 数据生成器与评估报告
- 怎样算完成
- 训练内外评价分开
- 共线性条件可复现
练到的知识点偏差方差和噪声 · Ridge闭式解 · 特征尺度与正则强度
思维拓展
先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。
- 作业 10思维拓展 · 反例构造
反驳或限定“增大正则系数一定改善泛化”:构造可在 CPU 上穷举的小型数据生成机制,先固定模型选择协议,再展示支持你论证的结果。
- 提交内容
- 生成器、预定协议及反例或边界
- 怎样算完成
- 真分布与有限样本分开
- 不事后只挑一条有利曲线
练到的知识点L2参数惩罚 · 验证集选择正则系数
完成后,再检验一次
给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。
继续阅读
先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。
- 必读参考文档英文
scikit-learn 1.7.2:Ridge 正规方程中的对角惩罚 (新标签页)↗
核对正规方程中对角 alpha 修正与线性求解,区分内部求解和外层截距处理。
- 深入参考文档英文
scikit-learn:Ridge (新标签页)↗
阅读目标函数、求解器和正则参数说明。
- 深入参考文档英文
Stanford CS229 Notes (新标签页)↗
阅读偏差方差、模型选择和正则化推导。
- 深入参考文档英文
scikit-learn:常见陷阱 (新标签页)↗
确认缩放与选择流程没有越过训练数据边界。