返回学习地图
llmPhase A · 第 5

04. 损失函数

MSE/MAE/交叉熵/BCE/Focal Loss/L1L2正则化:损失函数全面详解,从零概念到手算示例,为什么模型需要这些数学度量来学习

30 个章节·按类别展开/折叠
知识

损失函数是指南针

训练神经网络本质上是在做一件事:最小化损失函数

损失函数 L(ŷ, y) 衡量模型预测值与真实值之间的差距。损失越大,模型越差;损失越小,模型越好。优化器根据损失对权重的梯度(偏导数)来决定如何更新参数。

不同的任务需要不同的损失函数:

  • 回归任务(预测连续值,如房价、温度)→ MSE / MAE
  • 分类任务(预测离散类别,如猫/狗/鸟)→ 交叉熵(Cross-Entropy) / BCE
  • 不平衡分类(正负样本悬殊,如欺诈检测)→ Focal Loss
  • 防止过拟合 → 在损失中加入正则化项(L1/L2)

本章从零概念开始,逐一推导每个损失函数的数学本质,给出手算数值示例,以及为什么某些损失函数对特定任务更有效。学完之后你不仅能理解损失函数,还能在实际项目中合理选择。

知识

损失函数的三要素

任何损失函数都包含三个核心要素:

  1. 误差度量:如何计算预测与真实的差异(差、比、对数)
  2. 聚合方式:多个样本的误差如何合并(平均、求和、加权)
  3. 可微性:损失对预测值的导数必须存在(梯度下降需要)

这三种要素决定了损失函数的行为。

本章路线图:

  1. MSE(回归最基础)
  2. MAE(回归鲁棒版本)
  3. 交叉熵(多分类标准)
  4. BCE(二分类标准)
  5. 正则化(在损失中加入约束)

开始之前,请回顾【02. 优化器】中梯度下降的知识:损失函数的值决定了优化方向(负梯度方向)。

知识

第一节:MSE(均方误差)—— 回归任务最常用的损失函数

MSE = Mean Squared Error(均方误差),也叫 L2 Loss。

直觉理解:预测值与真实值的差距有多大?把它平方,再取平均。

数学定义:MSE = (1/N) ∑_{i=1}^{N} (y_i - ŷ_i)²

其中 y_i 是第 i 个样本的真实值,ŷ_i 是模型预测值,N 是样本数。

为什么平方?因为:

  • 放大错误:误差为2时损失为4,误差为10时损失为100——大误差受到额外惩罚
  • 处处可导:(ŷ - y)² 对 ŷ 求导 = 2(ŷ - y),梯度下降能正常进行(不像绝对值在0点不可导)
  • 对应高斯分布:最小化 MSE 等价于假设噪声服从高斯分布下的最大似然估计

从零推导——为什么 MSE 损失对应的梯度是 ŷ - y 的倍数?

对一个样本:L = (y - ŷ)²

对 ŷ 求偏导:∂L/∂ŷ = 2(ŷ - y)(链式法则)

这个导数告诉优化器:如果 ŷ > y(预测高了),导数 > 0,ŷ 需要减小;反之则增大。简单直观!

表格

MSE 参数与属性表

属性说明
输入形状(batch_size, 1) 或 (batch_size,)连续数值
输出形状标量(一个数字)所有样本误差的平均
值域[0, +∞)完美预测=0,无上限
导数dL/dŷ = 2(ŷ - y) / N对每个样本的预测值
对异常值敏感度(平方放大)单个大误差会主导损失
适用场景回归、噪声高斯分布房价、温度、价格预测
PyTorch APInn.MSELoss()默认返回均值
是否可微处处可导
知识

MSE 的变体:RMSE 和 MAE

RMSE(均方根误差):RMSE = √(MSE)

开方后将量纲还原到原始单位。如果房价预测的 MSE = 100万²,RMSE = 10万,更容易理解模型误差大概在什么数量级。

MAE(平均绝对误差):MAE = (1/N) ∑ |y_i - ŷ_i|

也叫 L1 Loss。对异常值不敏感(没有平方),但在0点不可导。梯度始终为 ±1,更新更稳定但不收敛更快。

Huber Loss:MSE 和 MAE 的混合体。小误差用 MSE(精确),大误差用 MAE(鲁棒)。在 |ŷ - y| < δ 时使用 MSE,否则使用 MAE。超参数 δ 控制切换点。

什么时候用哪个?

  • MSE:数据干净、无异常值——最常用
  • MAE:数据含异常值(不想被异常主导演练)
  • Huber:折中方案,工程实践中常用
  • RMSE:需要可解释的单位时用
实例

MSE 手算示例:房价预测

实例

场景:我们训练一个模型预测 3 套房子的价格(万元)。

房子真实价格 y预测价格 ŷ误差 e = y - ŷ平方误差 e²
110095525
2200210-10100
315014010100

计算:MSE = (25 + 100 + 100) / 3 = 225 / 3 = 75

单位:万元²。RMSE = √75 ≈ 8.66 万元。

对比 MAE:MAE = (5 + 10 + 10) / 3 = 25/3 ≈ 8.33 万元。

注意:因为平方,MSE (75) 远大于 MAE 的平方 (8.33² ≈ 69.4)?不对,这里只是巧合。关键是 MSE 惩罚了大误差。如果第三个预测改为 120(误差 30):

MSE = (25 + 100 + 900) / 3 ≈ 341.67(比原来高 4.6 倍!)

MAE = (5 + 10 + 30) / 3 = 15(只高 1.8 倍)

这就是“平方放大了大误差”的含义。

练习

MSE 练习(5 题)

练习

Q1:真实值 [2, 4, 6, 8],预测值 [2.5, 3.5, 6.5, 7.5]。计算 MSE 和 MAE。

Q2:如果 Q1 的预测中有一个样本误差为 50(异常值),其他预测不变,MSE 和 MAE 分别变成多少?哪个变化更大?为什么?

Q3:证明 MSE 对 ŷ_i 的偏导数为 ∂L/∂ŷ_i = 2(ŷ_i - y_i) / N。

Q4:在 PyTorch 中,MSE 的 reduction 参数可以设为 'mean' 或 'sum'。两者在梯度上有何区别?训练时应该用哪个?

Q5:假设你预测气温,RMSE=3°C。一个同事说他的模型 MAE=2.5°C。谁的模型更好?为什么不能直接比较 RMSE 和 MAE?

查看答案

A1:误差: [-0.5, 0.5, -0.5, 0.5]。平方: [0.25, 0.25, 0.25, 0.25]。MSE = 1.0/4 = 0.25。MAE = (0.5+0.5+0.5+0.5)/4 = 0.5

A2:假设第 1 个真实值 2 预测为 -48,误差 50。平方误差 = 2500。MSE = (2500+0.25+0.25+0.25)/4 = 2500.75/4 ≈ 625.19(增长了 2500 倍!)。MAE = (50+0.5+0.5+0.5)/4 = 51.5/4 = 12.875(只增长 26 倍)。原因:平方放大了异常值。

A3:L = (1/N)∑(y_i - ŷ_i)²。∂L/∂ŷ_j = (1/N)×2(y_j - ŷ_j)×(-1) = -2(y_j - ŷ_j)/N = 2(ŷ_j - y_j)/N。对 j ≠ i 的项偏导为 0。

A4:'mean' 除 N 使梯度稳定(与 batch size 无关),'sum' 不除所以梯度随 batch 增大而增大。训练一般用 'mean',方便调学习率。'sum' 需根据 batch size 调整学习率。

A5:不能直接比较。RMSE=3 意味着平方误差均值=9,MAE=2.5 的平方均值=6.25。如果误差分布均匀(无极端值),RMSE≈MAE。RMSE 更大说明有较大误差样本。需看具体业务需求。

知识

第二节:交叉熵(Cross-Entropy)—— 分类任务的标准损失函数

交叉熵(Cross-Entropy Loss,简称 CE)是多分类任务最常用的损失函数。配合 Softmax 使用。

直觉理解:两个概率分布有多像?如果模型预测的概率分布和真实标签分布越接近,交叉熵越小。

从信息论说起:

信息量:一个事件发生的概率越低,它包含的信息量越大。数学上:I(x) = -log₂(P(x))。单位是比特(bit)。

熵(Entropy):对随机变量不确定性的度量。H(P) = -∑ P(x) log P(x)。熵越大,不确定性越大。

交叉熵(Cross-Entropy):H(P, Q) = -∑ P(x) log Q(x) = H(P) + Dₖ₁(P||Q)

其中 P 是真实分布(标签),Q 是预测分布。交叉熵 = 真实分布的熵 + KL 散度(两个分布的差异)。因为 H(P) 固定(标签的熵是常数),最小化交叉熵等价于最小化 KL 散度。

对分类任务:真实标签 y 是 one-hot 向量(正确类别=1,其他=0)。所以:

CE = -∑ᵢ y_i log(ŷ_i) = -∑_{正确类别} 1×log(ŷ_c) - ∑_{错误类别} 0×log(ŷ_i) = -log(ŷ_c)

也就是说:交叉熵实际上只关心模型对正确类别的预测概率。模型对正确类别的预测概率越高,交叉熵越低。如果模型对正确类别的预测概率是 0.99,CE ≈ 0.01;如果只有 0.1,CE ≈ 2.3。

知识

为什么分类任务不用 MSE?

重要问题:既然 MSE 是“万能”的误差度量,为什么分类问题要用交叉熵而不是 MSE?

原因 1——梯度消失问题:

分类输出通过 Softmax 得到了概率分布。如果模型完全错了(预测概率几乎 0),MSE 的梯度非常小(因为 Softmax 两端饱和),模型几乎学不动。但交叉熵的梯度 = ŷ - y,即使 ŷ 接近 0,也能给出接近 -1 的大梯度。

原因 2——概率解释:

交叉熵对应概率模型中的最大似然估计。最小化交叉熵等价于最大化模型生成正确标签的概率。而 MSE 对应高斯噪声假设,不适合离散标签。

数值对比:

三分类:真实 y=[1,0,0],预测 ŷ_c=0.001

MSE = (1-0.001)² + (0-0.499)² + (0-0.5)² ≈ 0.998 + 0.249 + 0.250 ≈ 1.497

交叉熵 = -log(0.001) ≈ 6.908

梯度 MSE:∂L/∂ŷ_c = 2(ŷ_c - y_c) = 2(0.001-1) = -1.998(很小)

梯度 CE:∂L/∂ŷ_c = (ŷ_c - y_c) / ŷ_c = (0.001-1)/0.001 = -999(很大!)

交叉熵在模型完全错误时给予巨大的梯度信号,强迫模型快速纠正。

表格

交叉熵参数与属性表

属性说明
输入形状logits: (batch_size, n_classes) 或 ŷ: (batch_size, n_classes)未归一化 logits 或 softmax 后概率
标签形状one-hot: (batch_size, n_classes) 或 class index: (batch_size,)整数标签更方便
输出值域[0, +∞)完美预测=0,越错越大
导数dL/dŷ_i = ŷ_i - y_i(softmax 输出时)美丽的简单形式!
对错误置信度惩罚极高概率 0.1 时损失 2.3,概率 0.001 时损失 6.9
适用场景多分类(>2 类)图像分类、文本分类、情感分析
PyTorch APInn.CrossEntropyLoss()内置 Softmax + NLLLoss,输入 logits 即可
与 Softmax 关系通常联合使用Softmax 输出概率,CE 计算损失
权重支持是(weight 参数)可对类别加权处理不平衡
实例

交叉熵手算示例:图像分类(3 类)

实例

场景:一张图片的真实类别是“猫”(类别 2,索引 1,0=狗,1=猫,2=鸟)。

模型输出 logits(未归一化分数):[0.5, 2.5, -1.0]

Step 1——Softmax 归一化:

exp(0.5) = 1.649, exp(2.5) = 12.182, exp(-1.0) = 0.368

sum = 1.649 + 12.182 + 0.368 = 14.199

ŷᴰ₨ = 1.649/14.199 = 0.116(狗)

ŷᴵᵃᵀ = 12.182/14.199 = 0.858(猫)

ŷᴰᵂᵀ = 0.368/14.199 = 0.026(鸟)

Step 2——交叉熵计算:

CE = -[0×log(0.116) + 1×log(0.858) + 0×log(0.026)] = -log(0.858) = 0.153

如果模型预测错误:logits [-1.0, 0.5, 2.5]

exp(-1.0)=0.368, exp(0.5)=1.649, exp(2.5)=12.182, sum=14.199

ŷ: [0.026, 0.116, 0.858]

CE = -log(0.116) = 2.154

错误时的损失(2.154)是正确时的(0.153)的 14 倍!这就是交叉熵“惩罚错误”的体现。

实例

交叉熵梯度推导:为什么 dL/dŷ = ŷ - y

实例

这是一个值得记住的经典结论:当 Softmax + Cross-Entropy 联合使用时,对 logit z_j 的梯度是 ŷ_j - y_j。

推导:

L = -∑_k y_k log(ŷ_k)

ŷ_j = e^{z_j} / ∑_k e^{z_k}

∂L/∂z_j = ∑_k (∂L/∂ŷ_k)(∂ŷ_k/∂z_j)

因为 ∂L/∂ŷ_k = -y_k / ŷ_k

且 ∂ŷ_k/∂z_j = ŷ_k(1 - ŷ_j) 当 k=j,= -ŷ_k ŷ_j 当 k≠j

代入得到:∂L/∂z_j = ŷ_j - y_j

这个形式极其优雅!梯度 = 预测概率 - 真实标签。如果模型预测过高(ŷ_j > y_j),梯度 > 0,需要降低该 logit;如果预测过低(ŷ_j < y_j),梯度 < 0,需要提升。

PyTorch 的 CrossEntropyLoss 直接输入 logits,内部自动做 Softmax + NLLLoss,所以不需要在模型输出手动加 Softmax。

练习

交叉熵练习(5 题)

练习

Q1:三分类真实标签 y = [0,1,0],预测概率 ŷ = [0.1, 0.8, 0.1]。计算交叉熵损失。

Q2:如果 ŷ = [0.001, 0.999, 0.000] 而不是 [0.1, 0.8, 0.1],交叉熵变成多少?两个模型正确类别的概率分别是 0.8 和 0.999,为什么厂商更青睐第二个模型?

Q3:对于 10 分类,logits = [3,1,0,2,-1,0.5,1.5,-2,0.8,0.3],真实类别索引=0。计算:(1) Softmax 输出 (2) 交叉熵损失 (3) 对 logit[0] 的梯度。

Q4:为什么 PyTorch 的 CrossEntropyLoss 建议输入 logits 而不是 Softmax 后的概率?
提示:考虑数值稳定性。

Q5:如果你的分类任务有 1000 个类别,但每个样本只属于 1 个类。交叉熵计算中一次只用到 log(ŷ_c) 还是用到了所有类别的预测?这说明了什么效率问题?

查看答案

A1:CE = -log(0.8) = 0.2231

A2:ŷ=[0.001,0.999,0.000]: CE = -log(0.999) ≈ 0.001。从损失看,第二个模型更好(损失低得多)。对关键应用(如医疗诊断),正确概率从 80% 提升到 99.9% 意义巨大。交叉熵能精细地区分这些差异,而准确率无法区分(都预测正确)。

A3:(1) exp(3)=20.086, exp(1)=2.718, exp(0)=1, exp(2)=7.389, exp(-1)=0.368, exp(0.5)=1.649, exp(1.5)=4.482, exp(-2)=0.135, exp(0.8)=2.226, exp(0.3)=1.350。sum=41.403。ŷ_0 = 20.086/41.403 ≈ 0.485。(2) CE = -log(0.485) ≈ 0.724。(3) 梯度 = ŷ_0 - y_0 = 0.485 - 1 = -0.515(需要提高 logit[0])。

A4:数值稳定性。如果直接对概率算 log(log(0.001) = -6.908),但若 logit 很大/很小,Softmax 后的概率可能下溢为 0,log(0) = -∞。PyTorch 的 CrossEntropyLoss 内部做了 log-softmax 合并(log-sum-exp trick),数值更稳定。

A5:CE = -∑ y_i log(ŷ_i) = -log(ŷ_c)。只用到了正确类别的预测概率。但为了得到 ŷ_c = exp(z_c)/∑exp(z_j),分母需要计算所有 1000 个类别的 exp 和 sum,所以计算复杂度是 O(C)=O(1000)。对海量类别(如词汇表 100k),分母计算成为瓶颈。

知识

第三节:BCE(二元交叉熵)—— 二分类问题的标准损失

BCE(Binary Cross-Entropy,二元交叉熵)是二分类任务的标准损失函数。

二分类:输出只有两个类(如:是/否、垃圾邮件/正常、患病/健康、正面/负面)。

两种等价形式:

形式 1(双项式):BCE = -[y·log(p) + (1-y)·log(1-p)]

其中 y ∈ {0,1} 是真实标签,p ∈ (0,1) 是模型预测的正类概率(通常经过 Sigmoid)。

形式 2(对数几率形式):BCE = -[(1-y)·log(1-σ(z)) + y·log(σ(z))]

其中 z 是模型输出的 logit,σ(z) = 1/(1+e^{-z}) 是 Sigmoid 函数。

为什么两项?

二分类中只有两种情况:

  • 当 y=1(正类):BCE = -log(p)。希望 p 越大越好(越接近 1)。
  • 当 y=0(负类):BCE = -log(1-p)。希望 1-p 越大越好(即 p 越小越好,越接近 0)。

两项合并成一个公式,优雅地覆盖了两种情况。

从零到 BCE——用 MLE 视角推导:

假设二分类服从伯努利分布(Bernoulli distribution)。模型预测 p = P(y=1|x)。

似然函数(给定参数下,看到训练数据的概率):L = Π_i p_i^{y_i} (1-p_i)^{1-y_i}

取负对数:-log L = -∑_i [y_i log(p_i) + (1-y_i)log(1-p_i)]

这正是 BCE!最大化似然 = 最小化 BCE。

知识

Sigmoid + BCE:梯度推导

对单个样本:L = -[y log(σ(z)) + (1-y) log(1-σ(z))]

利用 σ'(z) = σ(z)(1-σ(z)) 和链式法则:

dL/dz = -[y / σ(z) × σ(z)(1-σ(z)) - (1-y) / (1-σ(z)) × σ(z)(1-σ(z))]

= -[y(1-σ(z)) - (1-y)σ(z)]

= -[y - yσ(z) - σ(z) + yσ(z)]

= -σ(z) + y

= σ(z) - y

再次得到这个极其简单的形式!Sigmoid + BCE 对 logit z 的梯度 = 预测 σ(z) - 真实 y。

和多分类的 Softmax + CE 梯度形式完全一致(只是从向量变成了标量)。这说明Logistic Regression + Sigmoid + BCE本质上是一个 2 类 Softmax + CE 的特例。

表格

BCE 参数与属性表

属性说明
输入形状(batch_size, 1) 或 (batch_size,)logits(Sigmoid 之前的输出)
标签形状(batch_size, 1) 或 (batch_size,)0 或 1
输出值域[0, +∞)完美预测=0
导数dL/dz = σ(z) - y对 logit 的梯度
适用场景二分类、多标签分类垃圾邮件检测、CTR 点击率预测
多标签扩展每个标签独立 BCE一张图同时有[猫,狗,天空]
PyTorch APInn.BCEWithLogitsLoss()内置 Sigmoid + BCE(推荐)
nn.BCELoss()需要先手动 Sigmoid数值不稳定,不推荐
权重支持是(pos_weight 参数)处理正负样本不平衡
知识

BCE 的变体:Focal Loss

Focal Loss = -α_t (1-p_t)^γ log(p_t)

其中 p_t = p 如果 y=1,= 1-p 如果 y=0。

为什么需要 Focal Loss?

在目标检测等任务中,负样本(背景)远超正样本(物体)。模型很快学会了正确预测背景,梯度变小——但背景样本仍然占据大部分损失。

调制因子 (1-p_t)^γ:当 p_t 接近 1(模型已正确且有信心),调制因子趋近 0,该样本的贡献大幅降低。当 p_t 很小(模型还在犯错),调制因子接近 1,损失保留。

平衡因子 α_t:控制正负样本权重。常用 α=0.25, γ=2(原论文推荐)。

对比:

  • BCE:简单易分析样本的损失 = -log(0.9) ≈ 0.105;难分析 = -log(0.1) ≈ 2.303
  • Focal (γ=2):简单 = -(0.1)²×log(0.9) ≈ 0.001(下降 99%);难 = -(0.9)²×log(0.1) ≈ 1.864(下降 19%)

Focal Loss 让模型更专注于“难”样本。

实例

BCE 手算示例:垃圾邮件检测

实例

场景:垃圾邮件检测,1=垃圾邮件,0=正常邮件。

样本真实 yLogit zSigmoid σ(z)BCE 项
邮件 112.50.924-1×log(0.924)=0.079
邮件 20-1.00.269-(1-0)×log(1-0.269)=0.313
邮件 31-0.50.378-1×log(0.378)=0.973
邮件 401.50.818-(1-0)×log(1-0.818)=1.704

BCE = (0.079 + 0.313 + 0.973 + 1.704) / 4 = 3.069 / 4 ≈ 0.767

分析:

  • 邮件 1:预测 0.924,真实 1,损失小。模型正确且有信心。
  • 邮件 2:预测 0.269(意味着检测为垃圾邮件的概率很低),真实 0,损失较小。正确。
  • 邮件 3:预测 0.378(更像正常邮件),真实 1,损失大。模型判断错了!
  • 邮件 4:预测 0.818(认定是垃圾邮件),真实 0,损失最大!模型严重错误且自信。

梯度(每个样本对 logit z 的导数):

dL/dz_1 = 0.924-1 = -0.076(需要提高 logit 来接近 1)

dL/dz_2 = 0.269-0 = 0.269(需要降低 logit 来接近 0)

dL/dz_3 = 0.378-1 = -0.622(大梯度,要尽快纠正)

dL/dz_4 = 0.818-0 = 0.818(最大梯度,严重错误且自信)

练习

BCE 练习(5 题)

练习

Q1:真实 y=[1,0,1,0],预测 p=[0.9, 0.2, 0.6, 0.8]。计算 BCE 均值和准确率。

Q2:证明 BCE 等价于 2 类的 Softmax + CE。提示:将 Sigmoid 输出和 Softmax 输出联系起来。

Q3:在 PyTorch 中,BCEWithLogitsLoss 和 BCELoss 有什么区别?在什么情况下应该用哪个?

Q4:正负样本极端不平衡时(如 1000:1),BCE 会有什么问题?如何用 pos_weight 缓解?写出 PyTorch 代码。

Q5:多标签分类(一张图同时包含“猫”和“狗”)如何用 BCE 实现?和 Softmax + CE 有什么区别?

查看答案

A1:样本 1: -log(0.9)=0.105;样本 2: -log(0.8)=0.223;样本 3: -log(0.6)=0.511;样本 4: -log(0.2)=1.609。BCE = (0.105+0.223+0.511+1.609)/4 = 0.612。准确率: 样本1✓(p>0.5), 样本2✓(p<0.5), ✗(p>0.5), 样本4✗(p>0.5)。准确率=2/4=50%。

A2:对两个类,Softmax 输出 [σ(z), 1-σ(z)],CE = -(y·log(σ(z)) + (1-y)·log(1-σ(z))),完全等价于 BCE。实际上 PyTorch 的 BCEWithLogitsLoss 内部用的就是 log-sum-exp 技巧。

A3:BCELoss 需要输入已经过 Sigmoid 的概率([0,1]),BCEWithLogitsLoss 输入 logits((-∞,+∞)),内部自动做 Sigmoid。推荐 BCEWithLogitsLoss 因为它做了数值稳定的 log-sum-exp 合并。如果手动 Sigmoid 再用 BCELoss,可能因为 exp 下溢导致 -log(0) = ∞。

A4:正样本(1)占比极少,BCE 对每个负样本的惩罚总和可能超过正样本,模型偏向预测 0。可以通过 pos_weight 给正样本更高权重:loss_fn = nn.BCEWithLogitsLoss(pos_weight=torch.tensor([pos_ratio])),pos_ratio = 负样本数/正样本数 = 1000。这样正样本的损失权重是负样本的 1000 倍。

A5:多标签分类每个标签独立预测:y ∈ {0,1}^K,每个维度用 BCE 独立算损失。BCE_total = ∑_k BCE(y_k, p_k)。与 Softmax+CE 的区别:Softmax 强制所有类别概率和为 1(互斥),BCE 允许同时为 1(共存)。所以多标签必须用 BCE。

知识

第四节:正则化(Regularization)—— 让损失函数变得更聪明

前面的 MSE、CE、BCE 都只关注模型在训练数据上的表现。但如果模型过于关注训练数据(记住噪声),就会过拟合(Overfitting)——在训练集表现极好,但在测试集表现很差。

正则化就是在原有损失函数中加入一个额外惩罚项,约束模型的复杂度。

一般形式:

L_total = L_data + λ × R(w)

其中 L_data 是数据损失(MSE / CE / BCE),R(w) 是正则化项,λ 是正则化强度(超参数)。

正则化的直观理解:

  • 模型既要拟合数据(L_data 小),又要保持简单(R(w) 小)
  • λ 控制两者的平衡:λ 太小→过拟合,λ 太大→欠拟合
  • 正则化实现“奥卡姆剃刀”:在效果相同的情况下,选择更简单的模型

常见的正则化有两种核心方法:L1 正则化(Lasso)L2 正则化(Ridge)

知识

L2 正则化(权重衰减/Weight Decay)

定义:R(w) = ½ ∑_j w_j²

总损失:L_total = L_data + λ/2 · ∑_j w_j²

系数 ½ 是为了求导方便(消掉平方的 2)。

名字由来(权重衰减):在 SGD 更新中:

w ← w - α(∂L_data/∂w + λw) = w(1-αλ) - α∂L_data/∂w

每一步更新前先乘以 (1-αλ) < 1——权重被“衰减”了。

为什么 L2 有效?

  • 防止大权重:模型对某个特征过分依赖时权重会很大,L2 惩罚大权重
  • 平滑输出:小权重让输出变化更平缓,减少对噪声的敏感
  • 在贝叶斯视角下:L2 对应于权重服从高斯分布的 Laplace 先验假设
知识

L1 正则化(Lasso)

定义:R(w) = ∑_j |w_j|

总损失:L_total = L_data + λ · ∑_j |w_j|

梯度:∂R/∂w_j = sign(w_j)(在 w_j=0 时不可导)

sign(x) = 1 如果 x>0,= -1 如果 x<0。

L1 vs L2 核心区别——稀疏性:

L1 会产生稀疏解(许多权重恰好为 0),而 L2 将权重缩放到接近 0 但不为 0。

为什么?几何直觉:

  • L1 的等值面是菱形(有尖角),最优点更容易落在坐标轴上
  • L2 的等值面是圆形(光滑),最优点通常不在坐标轴上

L1 适合:特征选择(很多无关特征自动权重=0)

L2 适合:所有特征都有用,但阻止某个特征太过重要

表格

正则化方法对比表

属性L1(Lasso)L2(Ridge/Weight Decay)Elastic Net
公式λ∑|w|(λ/2)∑w²λ₁∑|w| + λ₂∑w²
可微性w=0 不可导处处可导w=0 不可导
权重效果部分权重→0(稀疏)所有权重→小值稀疏 + 分组效应
特征选择自带特征选择无自动特征选择折中
相关特征处理随机选一个
(丢弃其他)
所有特征一起缩小保留相关特征组
典型 λ 值0.001~0.10.0001~0.01λ₁/λ₂=0.5
优化方法次梯度/ProximalSGD(Weight Decay)Proximal
PyTorch需手动实现optimizer=SGD(..., weight_decay=λ)需手动实现
适用场景高维稀疏特征默认正则化方法高维+特征分组相关
实例

L1 vs L2 正则化手算示例

实例

场景:一个简单线性回归 y = w₁x₁ + w₂x₂。数据损失 MSE = 2.0(当前权重下的误差)。

Case 1:w = [5.0, 0.1],λ = 0.1

L1 惩罚 = 0.1 × (5.0 + 0.1) = 0.51 → L_total = 2.0 + 0.51 = 2.51

L2 惩罚 = (0.1/2) × (25.0 + 0.01) = 0.05 × 25.01 = 1.25 → L_total = 2.0 + 1.25 = 3.25

Case 2:w = [3.5, 2.0](权重更分散但总和大一些)

L1 惩罚 = 0.1 × (3.5 + 2.0) = 0.55 → L_total = 2.0 + 0.55 = 2.55

L2 惩罚 = (0.1/2) × (12.25 + 4.0) = 0.05 × 16.25 = 0.8125 → L_total = 2.0 + 0.81 = 2.81

关键观察:

Case 1 vs Case 2:L1 更喜欢 Case 1(2.51 < 2.55),因为 L1 鼓励稀疏(大权重 5.0 + 小权重 0.1 的组合惩罚更小)。L2 更喜欢 Case 2(2.81 < 3.25),因为 L2 惩罚平方,散分布比集中分布惩罚更小。

这一点说明了“L1 鼓励稀疏、L2 缩所有权重”的核心差异。

实例

正则化对过拟合的影响:模拟实验

实例

模拟数据:y = x² + ε(ε ~ N(0, 0.1)),训练集 20 个点,测试集 100 个点。

无正则化(λ=0):

  • 模型使用 9 次多项式(10 个参数拟合 20 个点)
  • 训练 MSE ≈ 0.0001(几乎完美拟合噪声)
  • 测试 MSE ≈ 5.2(剧烈震荡,完全不能用)
  • 权重极大(部分 > 500)

L2 正则化(λ=0.01):

  • 训练 MSE ≈ 0.05(比无正则化略大,但合理)
  • 测试 MSE ≈ 0.15(远好于无正则化!)
  • 权重变小(最大约 3)

L2 正则化(λ=0.1):

  • 训练 MSE ≈ 0.12(更大)
  • 测试 MSE ≈ 0.18(接近二次函数的真实表现)
  • 权重很小(最大约 0.5)

λ 太大(λ=1.0):

  • 训练 MSE ≈ 0.8(严重欠拟合)
  • 测试 MSE ≈ 0.9(同样差)
  • 权重接近 0(模型几乎退化为常数)

结论:λ 存在最优值。太小→过拟合,太大→欠拟合。通常通过验证集选择最佳 λ。

知识

深度学习中的其他正则化技术

除了 L1/L2 正则化,深度学习还有许多其他正则化方法,它们在更复杂的模型中非常关键:

Dropout:

训练时以概率 p 随机丢弃神经元。p=0.5。这不是损失函数的一部分,但效果类似正则化。

每次训练迭代使用不同的“子网络”,测试时使用所有神经元。

Batch Normalization:

对每层输入做标准化(减均值除方差),引入可学习参数 γ 和 β。轻微正则化效果。

Early Stopping:

监控验证集损失,当验证集损失不再下降时停止训练。是最简单的正则化。

Data Augmentation:

对输入数据做随机变换(旋转/裁剪/翻转/颜色抖动)。让模型看到更多变体。

Label Smoothing:

将硬标签 (one-hot: [1,0,0]) 变为软标签 ([0.9, 0.05, 0.05])。防止模型过度自信。公式:y_smooth = (1-ε) × y_onehot + ε / K

这些技术和 L1/L2 正则化并不互斥,可以组合使用。

练习

正则化练习(5 题)

练习

Q1:一个线性模型有 3 个权重 w=[3, -2, 0.5],L1 和 L2 惩罚各是多少(λ=0.1)?如果 λ=1.0 呢?

Q2:为什么 L1 正则化能产生稀疏解(权重恰好为 0)而 L2 不能?用几何或代数解释。

Q3:在 PyTorch 的 SGD 优化器中设置 weight_decay=0.01 相当于什么正则化?它的作用范围是所有参数还是某些层?如何对不同层设置不同的 weight_decay?

Q4:给定一个 10 维特征的问题,你认为哪些特征可能是噪声。比较 L1(λ=0.1)和 L2(λ=0.1)在训练后的特征权重会有什么不同?假设数据损失相同。

Q5:Label Smoothing 为什么能算作正则化?它和交叉熵结合时的数学形式是什么?

查看答案

A1:L1(λ=0.1)=0.1×(|3|+|-2|+|0.5|)=0.1×5.5=0.55。L2(λ=0.1)=0.05×(9+4+0.25)=0.05×13.25=0.6625。λ=1.0: L1=5.5, L2=0.5×13.25=6.625。

A2:几何解释:L1 的约束区域是菱形(|w₁|+|w₂|≤C),有尖角在坐标轴上。等损失线(椭圆)与尖角相交的概率更高,导致 w₂=0。L2 的约束区域|圆形(w₁²+w₂²≤C),光滑无尖角。代数解释:L1 的次梯度在 0 点包含 [-1,1] 区间,当数据梯度在这个范围内时,权重稳定在 0。

A3:Weight decay 对应 L2 正则化。默认对所有参数(权重和偏置)添加。通常应该只对权重做正则化(不对偏置)。不同层设置:可以实例化两个 optimizer group:optim.SGD([{'params': model.fc1.parameters(), 'weight_decay': 0.01}, {'params': model.bias_param.parameters(), 'weight_decay': 0}], lr=0.01)。

A4:L1:无关特征的权重会被推到恰好 0(如 w₇=0, w₈=0, w₉=0),有效特征保留显著权重。L2:所有 10 个权重都变小,但噪声特征不会恰好为 0(如 w₇=0.02, w₈=-0.01),在测试时仍会产生微小噪声。[补充:在深度网络中,L2 也有效防止单个特征主导。]

A5:Label Smoothing 防止模型输出极端概率(1.0 或 0.0),限制模型置信度,起到正则化效果。与 CE 结合:L = -(1-ε)·log(ŷ_c) - ε/K·∑_{k}log(ŷ_k)。第一项鼓励正确类别概率高,第二项惩罚对其他类别概率为 0。ε 常见 0.1。

知识

第五节:损失函数选择指南

面对实际问题,如何选择合适的损失函数?以下是综合决策流程:

Step 1——确定任务类型:

  • 回归:MSE(默认)、MAE(有异常值)、Huber(折中)
  • 二分类:BCE(默认)、Focal(不平衡)
  • 多分类(互斥):Cross-Entropy(默认)
  • 多标签(非互斥):多标签 BCE(每个标签独立)

Step 2——检查数据质量:

  • 有异常值 → 回归用 Huber / MAE
  • 类别不平衡 → 分类用加权损失 / Focal Loss / 过采样
  • 标签有噪声 → Label Smoothing、Huber

Step 3——防止过拟合:

  • L2 正则化(Weight Decay):默认必加,λ=1e-4~1e-5
  • 高维稀疏特征 → L1 正则化
  • 深度学习模型 → Dropout+BatchNorm+Weight Decay 组合

损失函数的宇宙:除上述外还有 Contrastive Loss、Triplet Loss(度量学习)、CTC Loss(序列对齐)、Wasserstein Loss(GAN)等。但理解了本章的核心,再学其他损失函数会非常快。

表格

损失函数速查表

损失函数任务输出激活PyTorch API梯度形式
MSE回归无(线性输出)nn.MSELoss()2(ŷ - y) / N
MAE (L1)回归(鲁棒)nn.L1Loss()sign(ŷ - y) / N
Huber回归(折中)nn.SmoothL1Loss()(ŷ-y)/N 或 sign(ŷ-y)
Cross-Entropy多分类Softmax(自动)nn.CrossEntropyLoss()ŷ - y(对 logit)
BCE二分类Sigmoidnn.BCEWithLogitsLoss()σ(z) - y(对 logit)
Focal不平衡二分类Sigmoid需手动实现-α(1-p_t)^γ[γp_t log(p_t) - 1]
L1 正则防过拟合手动λ×sign(w)
L2 正则防过拟合weight_decayλ×w
练习

综合练习(3 题)

练习

Q1(设计题):你有以下三个机器学习任务:

A. 预测明天某股票涨跌幅(连续值,可能有异常冲击)

B. 手写数字识别(10 类,MNIST 风格)

C. 检测一段音频中是否包含特定口令(关键词检测,正样本极少)

请为每个任务推荐:(1)损失函数 (2)输出层激活函数 (3)是否需要正则化

Q2(分析题):一个模型在训练集上 CE=0.01,在测试集上 CE=2.5。这是过拟合还是欠拟合?你会在下一步怎么做?

Q3(数学题):证明当真实标签 y=1 时,交叉熵损失 = -log(p) 的 Hessian 矩阵(二阶导数)永远是正半正定的,说明损失函数是凸的。这对优化意味着什么?

查看答案

A1:A. Huber Loss(MAE 也可),线性输出,加 weight_decay=L2;B. CrossEntropyLoss,Linear→10 类 logits;C. BCE/Focal(正样本极少用 Focal),Sigmoid 输出,加 L2 正则+过采样。

A2:测试集损失远高于训练集,明显过拟合。下一步:增加正则化系数(更大的 L2),增加 dropout(如果有全连接层),减少模型复杂度(减少层数/宽度),收集更多训练数据。

A3:对单样本,y=1 时 L=-log(p)。p=σ(z)=1/(1+e^{-z})。d²L/dz² = d(σ(z)-1)/dz = σ(z)(1-σ(z)) > 0(因为 σ(z) ∈ (0,1))。Hessian > 0,函数凸。这对优化的意义:凸函数有唯一全局最小点,SGD一定能收敛到全局最优(不会陷入局部最优)。Logistic Regression 的 BCE 是凸优化问题。