线性回归


1. 线性回归核心思想

1.1 什么是线性回归

线性回归是一个监督学习中的回归类算法
核心思想:利用回归方程(也就是一个函数)对特征值(自变量)和目标值(因变量)之间的关系进行建模,通过训练数据学习出一组合适的参数,使得预测值尽可能接近真实值。

线性回归的数学表达为:

y ^ = w 1 x 1 + w 2 x 2 + ⋯ + w n x n + b \hat{y} = w_1x_1 + w_2x_2 + \dots + w_nx_n + b y^=w1x1+w2x2++wnxn+b

写成矩阵形式:

y ^ = X w + b \hat{y} = Xw + b y^=Xw+b

其中 w w w 是权重向量, X X X 是特征矩阵, b b b 是偏置项。三者都是矩阵,模型输出就是特征与权重的线性组合。


1.2 “线性”到底指什么?

一开始我也困惑:线性回归只能拟合直线(或平面)吗?如果特征里出现 ,还是不是线性回归?

答案:线性回归的“线性”,是指对参数 w 线性,而不是对特征 x 线性

一个模型只要能够写成:

y ^ = w 0 + w 1 ϕ 1 ( x ) + w 2 ϕ 2 ( x ) + ⋯ + w m ϕ m ( x ) \hat{y} = w_0 + w_1 \phi_1(\mathbf{x}) + w_2 \phi_2(\mathbf{x}) + \dots + w_m \phi_m(\mathbf{x}) y^=w0+w1ϕ1(x)+w2ϕ2(x)++wmϕm(x)

且满足:

  • ϕ i ( x ) \phi_i(\mathbf{x}) ϕi(x)任意关于原始特征的变换(可以是 x 2 x^2 x2 sin ⁡ ( x ) \sin(x) sin(x) log ⁡ x \log x logx x 1 x 2 x_1x_2 x1x2 等均可)
  • 每个 w i w_i wi 都以一次方的形式出现,且彼此不相乘、不相除、不嵌套

那么,它就是线性回归模型,哪怕 ϕ i ( x ) \phi_i(\mathbf{x}) ϕi(x)再扭曲,也不影响模型的“线性”身份。

举个例子

y = w₁x² + w₂√x + w₃sin(x) + b          ✅ 线性回归
y = w₀ + w₁x₁ + w₂x₂ + w₃x₁x₂ + w₄x₁²   ✅ 线性回归
y = w²x + b                              ❌ 不是线性回归(参数出现平方)

虽然 x 经过了平方、开根号、正弦变换,但 w₁、w₂、w₃ 依然是一次幂,这仍然是线性回归。模型拟合出来的依旧是一个超平面,只不过是在由 x²、√x、sin(x) 构成的新特征空间里的平面。

欧克,看到这里我们又注意到一个关键信息,让我们再理解一下:“模型拟合出来的依旧是一个超平面,只不过是在由 x²、√x、sin(x) 构成的新特征空间里的平面”好~这里我们从根本理解“线性”。


1.3 从几何理解“线性”本质

假设我们构造了这样一组特征: z 1 = x , z 2 = x 2 , z 3 = sin ⁡ ( x ) z_1 = x, z_2 = x^2, z_3 = \sin(x) z1=x,z2=x2,z3=sin(x)
模型就可以写成: y ^ = w 0 + w 1 z 1 + w 2 z 2 + w 3 z 3 \hat{y} = w_0 + w_1 z_1 + w_2 z_2 + w_3 z_3 y^=w0+w1z1+w2z2+w3z3
现在,我们把这些 z 1 , z 2 , z 3 z_1, z_2, z_3 z1,z2,z3 当作三个独立的坐标轴。那么上式就是一个关于 z z z 的线性方程,也就是说在由 ( z 1 , z 2 , z 3 , y ) (z_1, z_2, z_3, y) (z1,z2,z3,y) 张成的四维空间中,它代表一个超平面(三维平面)。

这就是"线性回归的’线性’是指对参数 w w w 线性"这句话的几何直观:无论原始特征 x x x 经过多么复杂的变换 ϕ i ( x ) \phi_i(x) ϕi(x),只要我们把变换后的新特征 z i = ϕ i ( x ) z_i = \phi_i(x) zi=ϕi(x) 看作新的坐标轴,模型在 z z z 空间里就是线性的(一个超平面)。

因此,线性回归的“线性“本质上是参数空间的线性,而不是原始特征空间的线性。非线性不是模型带来的,是特征工程带来的。

在原始特征空间看y=x^2+x 当然就是一个曲线对吧。


1.4 线性回归的分类

根据特征数量划分:

  • 单变量回归(简单线性回归):只有一个特征 x,形式为 y = wx + b
  • 多元回归(多重线性回归):有多个特征 x₁, x₂, …, xₙ

两者本质相同,只是特征矩阵 X 的列数不同。单变量回归就是多元回归在 n=1 时的特例。

需要注意的是,单变量/多变量的划分依据是原始输入特征的数量。即使我们做了多项式扩展(比如将 x x x 扩展为 x , x 2 x, x^2 x,x2),模型在输入层面仍然是单变量,但算法内部是以多变量线性回归的方式在运作(算法内部就是把 x 和 x² 当成两个独立维度,在这两个维度张成的空间中拟合一个超平面)。


2. 工作流程

线性回归不像 KNN 那样在预测时才临时计算,它有一套清晰的训练 - 预测两阶段流程。

训练阶段(核心:让机器自己总结规律)

  1. 接收训练数据:给定包含 m 个样本的训练集,每个样本有 n 个特征,以及对应的真实目标值 y
  2. 定义模型形式:确定使用线性方程 ŷ = X·w + b 来表达特征与目标的关系,其中 wb 是待学习的参数。
  3. 初始化参数:通常将所有权重 w 和偏置 b 初始化为随机值或零。
  4. 定义损失函数:选择一个衡量预测误差的函数(默认为均方误差 MSE),它的值越小表示模型拟合得越好。
  5. 选择优化算法:决定用哪种算法寻找让损失最小的参数,可以直接求解析解(正规方程),也可以用梯度下降类方法逐步逼近。
  6. 迭代更新参数(若用迭代法)
    • 计算当前参数下的损失函数梯度;
    • 沿负梯度方向更新参数,学习率控制步长;
    • 重复直到损失收敛或达到最大迭代次数。
      (若使用正规方程,则直接通过矩阵运算一步解出最优参数,没有迭代过程。)
  7. 输出训练好的模型:保存最终的 wb,训练结束。

预测阶段

  1. 接收新样本:给定一个或多个待预测样本的特征向量 x_new
  2. 代入方程计算:使用训练好的参数,直接计算 ŷ = x_new·w + b
  3. 输出预测值ŷ 即为该样本的连续值预测结果。

回顾之前笔记,我们可以知道机器学习是基于模型的算法,它会根据已有数据自己总结规律。我们不需要深究内部每一步具体是怎么编码构造函数的,但需要清楚它如何定义好坏(损失函数) 以及 如何优化(优化方法及正则化)
在这里插入图片描述


3. 损失函数

3.1 损失值是什么?

模型预测的结果和真实结果之间存在误差,也叫做损失值。损失函数的作用就是把这种误差量化成一个具体的数值,让我们可以衡量当前模型有多"差"。而我们训练模型的目标就是让这个数值尽可能小

3.2 常用损失函数

  • 均方误差 MSE(Mean Squared Error):
    M S E = 1 n ∑ i = 1 n ( y ^ i − y i ) 2 MSE = \frac{1}{n} \sum_{i=1}^{n} (\hat{y}_i - y_i)^2 MSE=n1i=1n(y^iyi)2
    对每个样本的预测误差求平方,再取平均。因为是平方,大误差会被放大,模型会更关注那些预测偏差大的样本。

  • 误差平方和 SSE(Sum of Squared Errors)
    S S E = ∑ i = 1 n ( y ^ i − y i ) 2 SSE = \sum_{i=1}^{n} (\hat{y}_i - y_i)^2 SSE=i=1n(y^iyi)2
    就是 MSE 不除以 n,只求和。本质上和 MSE 表达的信息一样,只是差了一个常数因子。在线性回归的数学推导中用 SSE 更常见,因为求导时消掉常数更简洁。选择 MSE 还是 SSE 不影响最终优化结果,只影响损失值的绝对大小,不改变最小值的位置。


4. 优化算法:如何找到最小化损失的参数

优化的本质问题:找到一组 w,使损失函数的值最小。这是一个"w 和损失值之间的函数"求最小值的问题。解决思路主要有两派:正规方程梯度下降

4.1 正规方程(Normal Equation)

思路直接:要求函数最小值,那就对 w 求导,令导数为 0,解出 w。

推导过程

  • 损失函数普通方式转成矩阵方式:

J ( w ) = ( h ( x 1 ) − y 1 ) 2 + ( h ( x 2 ) − y 2 ) 2 + ⋯ + ( h ( x m ) − y m ) 2 = ∑ i = 1 m ( h ( x i ) − y i ) 2 = ∥ X w − y ∥ 2 2 \begin{aligned} J(w) &= (h(x_1)-y_1)^2 + (h(x_2)-y_2)^2 + \dots + (h(x_m)-y_m)^2 \\ &= \sum_{i=1}^m (h(x_i)-y_i)^2 = \|Xw - y\|_2^2 \end{aligned} J(w)=(h(x1)y1)2+(h(x2)y2)2++(h(xm)ym)2=i=1m(h(xi)yi)2=Xwy22

  • 对损失函数 J ( w ) = ∥ X w − y ∥ 2 2 J(w) = \|Xw - y\|_2^2 J(w)=Xwy22 求导并令导数为零:
    2 ( X w − y ) X = 0 2 ( X w − y ) ( X X T ) = 0 X T 2 ( X w − y ) ( X X T ) ( X X T ) − 1 = 0 X T ( X X T ) − 1 2 ( X w − y ) = 0 X w = y X T X w = X T y \begin{aligned} 2(Xw - y)X &= 0 \\ 2(Xw - y)(XX^T) &= 0X^T \\ 2(Xw - y)(XX^T)(XX^T)^{-1} &= 0X^T(XX^T)^{-1} \\ 2(Xw - y) &= 0 \\ Xw &= y \\ X^TXw &= X^Ty \\\end{aligned} 2(Xwy)X2(Xwy)(XXT)2(Xwy)(XXT)(XXT)12(Xwy)XwXTXw=0=0XT=0XT(XXT)1=0=y=XTy
    如果 X T X X^TX XTX 可逆,则解为:

w = ( X T X ) − 1 X T y w = (X^TX)^{-1}X^Ty w=(XTX)1XTy

方阵不一定有逆矩阵。 XᵀX 可逆的前提是 X 的列向量线性无关(列满秩)。如果特征之间存在线性相关(多重共线性),XᵀX 就是奇异矩阵,无法求逆。这也是选择梯度下降而不选正规方程的一个理由。

正规方程的特点

  • 优点:一步到位,不需要迭代,不需要选学习率
  • 缺点:矩阵求逆的时间复杂度是 O(n³)(n 为特征数),特征维度高时非常慢;且 XᵀX 不可逆时无法使用。

4.2 梯度下降(Gradient Descent)

4.2.1 理解梯度

从二维开始:在二维空间(y = f(x))中,某一点的导数表示该点的斜率,含义是"当 x 发生微小变化时,y 发生怎样的变化"。

  • 导数的符号指明了变化的方向,即导数为正时,x增大会使y增大;导数为负时,y减小会使y减小。
  • 导数的数值告诉我们变化的剧烈程度。

可以想象二维空间平面,导数是切线,但是先不要过度限制在这个切线所指方向的思考,理解导数有正负取值,而我们探究的是x如何变化让y变小,x也只有向左向右移动(也就是变大变小的两种选择),而导数为正时,x增大会使y增大;导数为负时,y减小会使y减小。再来看导数是斜率这个点,斜率越大,也就是切线越陡峭,也就代表了x变化会使y变化越大。

推广到多维:上升到多维空间,函数在各个方向上的变化率由方向导数描述。

设方向向量为 l(单位向量),函数 f 沿 l 的方向导数为:
∂ f ∂ l = ∇ f ⋅ l = ∥ ∇ f ∥ ⋅ ∥ l ∥ ⋅ cos ⁡ θ \frac{\partial f}{\partial l} = \nabla f \cdot l = \|\nabla f\| \cdot \|l\| \cdot \cos\theta lf=fl=∥∇flcosθ
这个点积告诉我们:当 l 与梯度 ∇f 同向(夹角为0°)时,cosθ=1,方向导数取最大值,即函数上升最快;当夹角为180°(反向)时,方向导数取最小值,函数下降最快。
梯度就是那个向量,它指向函数值增长最快的方向,其模长表示增长的陡峭程度。 那么我们想要损失函数下降最快,自然应该朝负梯度方向更新参数。

理解梯度的方向和数值:

  • 方向:函数值增长最快的方向,即各个维度特征值如何变化,函数值变化最快。
  • 数值(模长):沿该方向函数值变化的陡峭程度。
4.2.2 梯度下降

我们的目标是让损失函数变小,而梯度指向的是函数增长最快的方向,恰好和我们想要的相反。所以要减去梯度,沿着梯度的反方向走,才是让损失值下降最快的方向。

参数更新公式

设损失函数为 L ( w ) L(\mathbf{w}) L(w),其中 w \mathbf{w} w 是待优化的参数向量。梯度下降的迭代公式为:
w new = w old − η ⋅ ∇ L ( w old ) \mathbf{w}_{\text{new}} = \mathbf{w}_{\text{old}} - \eta \cdot \nabla L(\mathbf{w}_{\text{old}}) wnew=woldηL(wold)

  • w old \mathbf{w}_{\text{old}} wold:当前参数值
  • w new \mathbf{w}_{\text{new}} wnew:更新后的参数值
  • ∇ L ( w old ) \nabla L(\mathbf{w}_{\text{old}}) L(wold):损失函数在 w old \mathbf{w}_{\text{old}} wold 处的梯度
  • η \eta η学习率 (Learning Rate),一个正标量,控制每次更新的步长

拆成标量形式,假设参数 w 0 , w 1 , … , w n w_0, w_1, \dots, w_n w0,w1,,wn,则对第 j j j 个参数: w j : = w j − η ⋅ ∂ L ∂ w j w_j := w_j - \eta \cdot \frac{\partial L}{\partial w_j} wj:=wjηwjL

在这里插入图片描述

数值示例
L ( w ) = w 2 L(w) = w^2 L(w)=w2
这个函数的全局最小值在 w = 0 w=0 w=0 处。其梯度(导数)为:
d L d w = 2 w \frac{dL}{dw} = 2w dwdL=2w设初始值 w = 5 w=5 w=5,学习率 η = 0.3 \eta = 0.3 η=0.3,我们来手动模拟前几步:
第 1 步:

  • 当前 w = 5 w=5 w=5,梯度 = 2 × 5 = 10 = 2 \times 5 = 10 =2×5=10
  • 更新: w new = 5 − 0.3 × 10 = 5 − 3 = 2 w_{\text{new}} = 5 - 0.3 \times 10 = 5 - 3 = 2 wnew=50.3×10=53=2

第 2 步:

  • 当前 w = 2 w=2 w=2,梯度 = 2 × 2 = 4 = 2 \times 2 = 4 =2×2=4
  • 更新: w new = 2 − 0.3 × 4 = 2 − 1.2 = 0.8 w_{\text{new}} = 2 - 0.3 \times 4 = 2 - 1.2 = 0.8 wnew=20.3×4=21.2=0.8

第 3 步:

  • 当前 w = 0.8 w=0.8 w=0.8,梯度 = 2 × 0.8 = 1.6 = 2 \times 0.8 = 1.6 =2×0.8=1.6
  • 更新: w new = 0.8 − 0.3 × 1.6 = 0.8 − 0.48 = 0.32 w_{\text{new}} = 0.8 - 0.3 \times 1.6 = 0.8 - 0.48 = 0.32 wnew=0.80.3×1.6=0.80.48=0.32

第 4 步:

  • 当前 w = 0.32 w=0.32 w=0.32,梯度 = 2 × 0.32 = 0.64 = 2 \times 0.32 = 0.64 =2×0.32=0.64
  • 更新: w new = 0.32 − 0.3 × 0.64 = 0.32 − 0.192 = 0.128 w_{\text{new}} = 0.32 - 0.3 \times 0.64 = 0.32 - 0.192 = 0.128 wnew=0.320.3×0.64=0.320.192=0.128

可以看到, w w w 的值从 5 迅速衰减,每一步都更接近 0,而且越靠近 0 梯度越小,步长自然也越来越小,不会跨过最低点。

如果我们将学习率改为 η = 1.2 \eta=1.2 η=1.2,则在 w = 5 w=5 w=5 时:

  • 梯度 = 10 = 10 =10,更新 w = 5 − 1.2 × 10 = 5 − 12 = − 7 w = 5 - 1.2 \times 10 = 5 - 12 = -7 w=51.2×10=512=7
  • 下一步: w = − 7 w=-7 w=7,梯度 = 2 × ( − 7 ) = − 14 = 2 \times (-7) = -14 =2×(7)=14,更新 w = − 7 − 1.2 × ( − 14 ) = − 7 + 16.8 = 9.8 w = -7 - 1.2 \times (-14) = -7 + 16.8 = 9.8 w=71.2×(14)=7+16.8=9.8
  • 再下一步又跳回负值,开始大幅震荡,永远收敛不到 0。

这就是学习率对收敛行为的决定性影响:太小收敛慢,太大震荡甚至发散。

在这里插入图片描述

4.2.3 梯度下降的变体

根据每次计算梯度时用多少样本参与,分为三种:

变体 每次梯度计算用多少样本 更新公式 特点
批量梯度下降(BGD) 全部 m m m 条样本 w j : = w j − η ⋅ 1 m ∑ i = 1 m ( y ^ ( i ) − y ( i ) ) x j ( i ) \displaystyle w_j := w_j - \eta \cdot \frac{1}{m}\sum_{i=1}^{m} (\hat{y}^{(i)} - y^{(i)}) x_j^{(i)} wj:=wjηm1i=1m(y^(i)y(i))xj(i) 稳定,但每次更新需要遍历全部数据,计算量大,不适合大数据集
随机梯度下降(SGD) 随机 1 条样本 w j : = w j − η ⋅ ( y ^ ( i ) − y ( i ) ) x j ( i ) w_j := w_j - \eta \cdot (\hat{y}^{(i)} - y^{(i)}) x_j^{(i)} wj:=wjη(y^(i)y(i))xj(i) 更新快,有噪声,可能震荡,但能跳出局部最优
小批量梯度下降(MBGD) 随机 k k k 条样本( 1 < k < m 1<k<m 1<k<m w j : = w j − η ⋅ 1 k ∑ i ∈ batch ( y ^ ( i ) − y ( i ) ) x j ( i ) \displaystyle w_j := w_j - \eta \cdot \frac{1}{k}\sum_{i\in \text{batch}} (\hat{y}^{(i)} - y^{(i)}) x_j^{(i)} wj:=wjηk1ibatch(y^(i)y(i))xj(i) 平衡了 BGD 的稳定性和 SGD 的速度,最常用

4.3 正规方程 vs 梯度下降

对比维度 正规方程 梯度下降
是否需要选学习率 不需要 需要
是否需要迭代 不需要,一步求解 需要多次迭代
特征维度高时 慢(矩阵求逆 O ( n 3 ) O(n^3) O(n3) 仍然可用
X T X X^TX XTX 不可逆时 无法使用 不受影响
适用场景 小规模数据,特征维度低 大规模数据,特征维度高

在这里插入图片描述


5. 正则化

注意不能一味追求极小的损失值,否则容易过拟合。

回顾:

  1. 欠拟合
    • 表现:训练集和测试集上表现都不好。
    • 本质:模型学到特征规律太少,模型太简单,表达能力不足。
    • 解决方向:增加特征维度、引入多项式特征、换更复杂的模型。
  2. 过拟合
    • 表现:训练集上表现很好,测试集上表现差。
    • 本质:模型学到了过多训练数据中的具体规律(包括噪声和偶然性),这些规律不属于我们想要学习的目标范围,模型太过复杂。
    • 解决方向
      1. 数据清洗:通过预处理清除噪声特征
      2. 增加数据集:让模型看到更多样的样本,学到真正的普遍规律
      3. 正则化:约束模型复杂度=

为什么欠拟合不能靠增加数据解决,过拟合却可以?
欠拟合的本质是模型本身太弱,就像用一个一次函数去拟合抛物线形状的数据,给你再多数据点,一次函数还是只能画一条直线。
过拟合的本质是模型太强但见识太少,它把训练集里那几个样本的死记硬背下来了,没有学到真正的规律。增加数据可以让模型看到更多变化,逼它从"背答案"变成"找规律"。

正则化的通俗理解:在损失函数后面加上一个关于权重 w 的惩罚项,制约模型不要过度依赖某些特征。


5.1 核心思路

原来的损失函数只关心"预测准不准":

L o s s = M S E ( 预测值 , 真实值 ) Loss = MSE(预测值, 真实值) Loss=MSE(预测值,真实值)

加上正则化后:
L o s s = M S E ( 预测值 , 真实值 ) + α ⋅ 惩罚项 ( w ) Loss = MSE(预测值, 真实值) + α · 惩罚项(w) Loss=MSE(预测值,真实值)+α惩罚项(w)

在损失函数末尾加一个与权重大小有关的惩罚项,优化时模型必须同时让原损失和惩罚项都变小,从而压抑不重要的权重。其中 α 是惩罚系数。α 越大,惩罚越重,模型就越不敢让 w 太大,对 w 的限制越强。

为什么要限制 w 的大小?如果一个特征的权重 w 很大,说明模型对这个特征非常"依赖",这个特征的微小变化都会引起预测结果剧烈波动。过拟合往往表现为某些 w 值异常大,模型为了拟合训练集中的个别样本而把某些特征的权重拉得很大。正则化就是给这种行为进行惩罚:你想让 w 变大来降低 MSE?可以,但要付出 α·惩罚项(w) 的代价。


5.2 L1 正则化(Lasso) vs L2 正则化(Ridge)

  1. L1 正则化(Lasso)
    惩罚项 = Σ ∣ w i ∣ 惩罚项 = Σ|wᵢ| 惩罚项=Σ∣wi
    线性惩罚:权重是 100,就惩罚 100;权重是 1,就惩罚 1。大权重和小权重受到的惩罚是等比例的。

  2. L2 正则化(Ridge)
    惩罚项 = Σ ( w i 2 ) 惩罚项 = Σ(wᵢ²) 惩罚项=Σ(wi2)
    平方惩罚:权重是 100,惩罚 10000;权重是 1,惩罚 1。大权重受到指数级加重的惩罚,对小权重则几乎没有惩罚。

  3. L1 vs L2 对比

维度 L1(Lasso) L2(Ridge)
惩罚项 Σ|wᵢ| Σ(wᵢ²)
惩罚方式 线性惩罚 平方惩罚
对大权重的态度 按比例约束 指数级打压
能否使 w 精确为 0 可以,产生稀疏解 不能,只能趋近于 0
特征选择 自动筛掉不重要的特征 保留所有特征但削弱

5.3 几何视角解释正则化:拉格朗日乘子与约束优化

前面讲的是“往损失函数里加一个惩罚项”的视角,数学上还有另一种完全等价的表述,用的是拉格朗日乘子法。

拉格朗日乘子法回顾:对于一个带约束的优化问题,在约束条件 g(w) = C 下求 f(w) 的最小值,解法是构造拉格朗日函数,令目标函数的梯度和约束函数的梯度平行。
几何含义是:想象约束条件 g(w) = C 在参数空间中画了一个圈,你只能在这个圈上行动。f(w) 的梯度指向 f 值增长最快的方向。你在圈上找一个点,如果圈在该点的切线方向和 f 的梯度方向不垂直,那你沿着圈往某个方向走,f 还会变小,说明当前点不是约束下的最小值。只有当 f 的梯度和圈的梯度方向平行(在同一条直线上),你才无处可去,圈上的任何微小移动都不会再让 f 变小。这个点就是约束下最优解,也就是切点。

正则化等价于给参数 w 画了一个范围圈,规定 w 只能在这个圈里面待着,然后在圈内(或圈上)找让损失最小的点。

  • L2 的圈是一个圆:w₁² + w₂² ≤ C
  • L1 的圈是一个菱形:|w₁| + |w₂| ≤ C

惩罚系数 α 和圈的大小 C 是一一对应的:α 越大,相当于圈越小(约束越紧);α = 0 相当于圈无限大(没有约束)。

分两种情形来看:

  1. 圈很大,损失函数的谷底就在圈里面:那你直接走到谷底就行,约束根本没起作用。对应 α 很小、模型几乎不受限制的情况。

  2. 圈很小,谷底在圈外面:你想去谷底但不准出去,只能走到圈的边界上,找一个“圈上最低的点”站着。这就是正则化起作用的情形:不要求损失绝对最小,而是要求在一个受约束的 w 范围内找最小。

那么为什么L1 为什么能产生稀疏解(w=0)?

把 L2(圆)和 L1(菱形)的约束圈和损失函数的等高线画在一张图上。

对于 L2(圆),边界是光滑的,没有尖角。在圆上,每个点都有唯一确定的切线方向,损失函数的等高线想切上来,必须正好对上那个特定方向,概率上比较"严格"。这就是 L2 只会把 w 往 0 方向压缩、但不会精确置零的几何原因。

对于 L1(菱形),边界有四个尖角,恰好落在坐标轴上。而在菱形的角上,这个点不存在唯一的切线,因为棱角处可以引出无数条支撑线而不穿入内部。数学上称其为次梯度,所有合法斜率的集合形成一个扇形。损失函数等高线在扩张过程中,有更高的概率先撞上菱形的角而不是边。而角上的点,至少有一个 w 分量恰好等于 0。

这就是 L1 正则化能够自动实现特征选择的几何本质:菱形的尖角使得许多权重被精确驱赶到零。


6. API 详解

前面我们详细拆解了线性回归中最重要的三个“可调组件”:

  • 损失函数:MSE / SSE 等
  • 优化算法:正规方程 / 梯度下降(还可细分批量、随机、小批量)
  • 正则化:无 / L1 / L2 等

不同的 sklearn 模型,其实就是对这三个组件做出了固定的或可配置的选择。


6.1 模块概览

线性回归相关的类都在 sklearn.linear_model 模块中:

模型 损失函数(默认) 优化算法 正则化 关键参数
LinearRegression MSE(最小二乘) 正规方程(SVD分解)
Ridge MSE + L2 惩罚项 正规方程 / 随机平均梯度等 L2,固定 alpha(λ) solver
Lasso MSE + L1 惩罚项 坐标下降 L1,固定 alphamax_iter
ElasticNet MSE + L1+L2 混合 坐标下降 L1+L2,可调混合比 alphal1_ratio
SGDRegressor 可自定义(默认MSE) 随机梯度下降 可自定义(默认L2) losspenaltyalphalearning_rate

6.2 LinearRegression :普通最小二乘

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
  • 损失函数:均方误差(MSE),无法更改。
  • 优化算法:内部使用奇异值分解(SVD)来求解最小二乘,等价于正规方程的稳定版。
  • 正则化:无。所以当特征多、样本少或存在共线性时,容易过拟合。
  • 优点:完全无超参数,无需调参,训练快(小数据)。
  • 适用场景:数据量不大、特征之间相关性弱、且确认不需正则化的简单任务。

理解 SVD
把特征矩阵 X X X 分解为三个矩阵的乘积:
X = U Σ V T X = U \Sigma V^T X=UΣVT
其中 Σ \Sigma Σ 是一个对角矩阵,对角线上的值叫奇异值。通过对奇异值“取倒数”的巧妙操作,可以直接得到最小二乘解:
w = V Σ + U T y w = V \Sigma^+ U^T y w=VΣ+UTy
这里 Σ + \Sigma^+ Σ+ Σ \Sigma Σ 的伪逆(对非零奇异值取倒数,零奇异值对应位置保持为 0)。

打个比方:

  • 正规方程相当于先给 X X X 来一次“平方”(计算 X T X X^TX XTX),原本只是稍微不可靠的方向,平方后会被放大成灾难;
  • SVD 则直接检查 X X X 本身在各个方向上的“可靠程度”(奇异值),遇到为零或极小的奇异值,就把对应方向在解中的贡献直接置零,相当于自动绕过那些“捣乱”的方向。
方式 稳定性 对不可逆的处理
直接求 ( X T X ) − 1 (X^TX)^{-1} (XTX)1 差,病态矩阵误差大 直接报错或解不可靠
SVD 求解 优秀,数值稳定 自动产生最小范数解,忽略零奇异方向

核心结论:SVD 不是一种新的优化算法,而是求解正规方程的数值稳定实现。本质还是在找解析解,只是走了一条更聪明的数学路径。你调用 LinearRegression() 时,背后自动执行的就是这套稳定的 SVD 解法。


6.3 带正则化的解析类模型:Ridge, Lasso, ElasticNet

这三者都在损失函数后加了惩罚项,通过解析或坐标下降等高效算法求解。

6.3.1 Ridge(岭回归):L2 正则化
from sklearn.linear_model import Ridge

ridge = Ridge(alpha=1.0)      # alpha 即 λ,越大惩罚越强
ridge.fit(X_train, y_train)
  • 固定配置:损失 = MSE + L2 惩罚,默认求解器会自动选择(正规方程或随机平均梯度等)。
  • 优化算法:由 solver 参数决定。可选值包括:
    • 'auto':根据数据自动选择(默认)。
    • 'svd':奇异值分解,稳定但计算稍重。
    • 'cholesky':利用 X^T X 的 Cholesky 分解,速度最快,适合样本多、特征不太多的场景。
    • 'sag':随机平均梯度下降,属于梯度下降的变体,适合大数据量。

    • 不同 solver 对正则化项的计算方式略有不同,但目标一致。
  • 关键参数
    • alpha:正则化强度,默认 1.0。调大 → 权重更趋于零,模型更简单。
  • 适用场景:特征间存在共线性、需要整体抑制模型复杂度但不要求特征选择。
6.3.2 Lasso: L1 正则化
from sklearn.linear_model import Lasso

lasso = Lasso(alpha=0.1, max_iter=10000)
lasso.fit(X_train, y_train)
  • 固定配置:损失 = MSE + L1 惩罚,优化算法为坐标下降。
  • 关键参数
    • alpha:惩罚力度,越大越容易让某些权重变为 0。
    • max_iter:迭代次数,Lasso 的求解比 Ridge 慢,数据量大时可能需要调大。
  • 适用场景:希望自动筛选重要特征,构建更简洁、可解释性强的模型。

理解坐标下降
梯度下降是沿着整个参数向量的梯度方向一起更新,而坐标下降是每次只更新一个坐标方向上的参数,固定其他参数不动,找到当前方向上的最小损失点,然后换下一个坐标。循环往复,直到总体收敛。因为 L1 惩罚项不可导(绝对值的次梯度问题),直接用梯度下降不好处理,而坐标下降在单变量优化时可以轻松处理带绝对值的子问题,所以 Lasso 和 ElasticNet 默认用它。

6.3.3 ElasticNet(弹性网络):L1 + L2 混合
from sklearn.linear_model import ElasticNet

en = ElasticNet(alpha=0.1, l1_ratio=0.5, max_iter=10000)
en.fit(X_train, y_train)
  • 固定配置:损失 = MSE + l1_ratio * L1 + (1 - l1_ratio) * L2,优化算法为坐标下降。
  • 关键参数
    • alpha:总惩罚力度。
    • l1_ratio:L1 惩罚的占比。0 时完全等同 Ridge,1 时等同 Lasso,中间值则两者兼具。
  • 适用场景:特征极多、高度相关时,纯 Lasso 可能随机选一个特征而忽略其他相关特征(不稳定);弹性网络通过加入 L2 部分使相关特征被一起保留或一起舍弃,稳定性更好。

6.4 SGDRegressor :梯度下降

这是前面梯度下降理论的直接对应,也是可配置性最高的线性回归类。

from sklearn.linear_model import SGDRegressor

model = SGDRegressor(
    loss='squared_error',      # 损失函数
    penalty='l2',              # 正则化类型
    alpha=0.0001,              # 正则化强度
    learning_rate='invscaling',# 学习率策略
    eta0=0.01,                 # 初始学习率
    max_iter=1000,             # 最大迭代次数
    tol=1e-3,                  # 收敛容忍度
)
model.fit(X_train, y_train)

关键参数

  • loss(默认 'squared_error'):损失函数。可选:

    • 'squared_error':MSE,标准线性回归用
    • 'huber':Huber 损失,对异常值更鲁棒
    • 'epsilon_insensitive':epsilon 不敏感损失(类似 SVM 回归)
  • penalty(默认 'l2'):正则化类型。可选:

    • 'l2':L2 正则化
    • 'l1':L1 正则化
    • 'elasticnet':L1 + L2 的混合
    • None:不使用正则化
  • alpha(默认 0.0001):正则化强度

  • learning_rate(默认 'invscaling'):学习率策略。可选:

    • 'constant':恒定学习率,η = eta0
    • 'optimal':按公式 η = 1/(α·(t+t₀)) 衰减
    • 'invscaling':eta = eta0 / pow(t, power_t),逐步缩小步长。
    • 'adaptive':自适应,损失不降时自动减小学习率
  • eta0(默认 0.01):初始学习率

  • max_iter(默认 1000):遍历数据的最大次数(epoch 数)

  • tol(默认 1e-3):收敛容忍度,损失下降小于此值则提前停止


6.5 注意前置处理:缩放与多项式特征

  1. 特征缩放:
    梯度下降对特征的尺度非常敏感。如果不同特征的数值范围差异很大(比如一个特征在 0~1,另一个在 0~10000),梯度在不同方向上的分量大小会严重失衡,导致优化路径来回震荡、收敛极慢。无论你选用哪个模型,只要涉及梯度下降或坐标下降,就一定要做特征缩放。正规方程类的模型虽不强制,但统一缩放能让系数具有可比性。

  2. PolynomialFeatures:多项式特征

    from sklearn.preprocessing import PolynomialFeatures
    
    poly = PolynomialFeatures(degree=2, include_bias=False)
    X_poly = poly.fit_transform(X)  # 生成 x1, x2, x1², x1x2, x2² 等
    
    • degree:最高次项的次数,为 2 时生成所有一次和二次组合。
    • include_bias:是否包含偏置列(全 1),线性模型通常自带偏置,可设为 False。

    应用场景:多项式特征的核心应用场景正是之前我们提到的欠拟合解决方法。当线性模型在训练集和测试集上都表现不佳,且怀疑原因是特征与目标之间存在明显的非线性关系时,就可以通过 PolynomialFeatures 构造平方项、交叉项等来增强模型的表达能力,使其在原始特征空间中能够拟合曲线或曲面。这本质上是在做特征工程,用更高维的映射赋予线性模型非线性威力。
    同时它也不仅限于欠拟合,即使模型复杂度足够,有时加入多项式特征还能进一步挖掘隐藏的非线性规律,但此时要注意配合正则化防止过拟合。


以上为个人学习总结,旨在梳理个人理解。如有疏漏或不当之处,欢迎指正与交流。如果文章对你有帮助,别忘了点个赞、留个言,让更多的小伙伴看到~ 我们下篇再见!

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐