一、损失函数

1. 什么是损失函数

损失函数(Loss Function) 在深度学习中是用来衡量模型参数质量的函数,衡量方式是比较网络输出和真实输出的差异。简单来说:损失越小,模型预测越准;损失越大,模型预测越离谱

2. 多分类任务损失函数

多分类任务中,通常使用 softmax 将 logits(网络原始输出)转换为概率形式,因此多分类的交叉熵损失也叫 softmax 损失

L=−∑kyklog⁡(S(f(x))k)L = -\sum_{k} y_k \log(S(f(x))_k)L=kyklog(S(f(x))k)

其中:

  • yyy 是样本 xxx 属于某一类别的真实概率(通常 one-hot 编码)
  • f(x)f(x)f(x) 是样本属于某一类别的预测分数( logits)
  • SSSsoftmax 激活函数,将预测分数转换成概率

从概率角度理解:我们的目的是最小化正确类别所对应预测概率的对数的负值,也就是让模型对正确类别的预测概率越高越好。

在 PyTorch 中使用 nn.CrossEntropyLoss() 实现:

import torch
import torch.nn as nn

# 设置真实值:可以是热编码后的结果,也可以不进行热编码
# 注意 y_true 的类型必须是 64 位整型数据
y_true = torch.tensor([1, 2], dtype=torch.int64)  # 真实类别索引
y_pred = torch.tensor([[0.2, 0.6, 0.2],
                       [0.1, 0.8, 0.1]], requires_grad=True, dtype=torch.float32)

# 实例化交叉熵损失(内部已包含 softmax + 损失计算)
loss = nn.CrossEntropyLoss()
my_loss = loss(y_pred, y_true).detach().numpy()
print('loss:', my_loss)

🔑 nn.CrossEntropyLoss() = Softmax + 交叉熵损失计算,不需要手动先做 softmax!


3. 二分类任务损失函数

二分类任务不再使用 softmax,而是使用 sigmoid 激活函数,损失函数相应调整为二分类交叉熵损失

L=−(ylog⁡(y^)+(1−y)log⁡(1−y^))L = -(y \log(\hat{y}) + (1-y) \log(1-\hat{y}))L=(ylog(y^)+(1y)log(1y^))

其中:

  • yyy 是真实标签(0 或 1)
  • y^\hat{y}y^ 是预测概率(sigmoid 输出,介于 0~1 之间)
import torch
import torch.nn as nn

# 预测值是 sigmoid 输出的结果(已经过 sigmoid 激活)
y_pred = torch.tensor([0.6901, 0.5459], requires_grad=True)
y_true = torch.tensor([0, 1], dtype=torch.float32)

# 实例化二分类交叉熵损失
loss = nn.BCELoss()
my_loss = loss(y_pred, y_true).detach().numpy()
print('loss:', my_loss)

4. 回归任务损失函数

回归任务预测的是连续值,损失函数衡量的是预测数值与真实数值的差距,常见三种:

4.1 MAE 损失函数(L1 Loss)

Mean Absolute Error(MAE) 以绝对误差作为距离:

L=1n∑i=1n∣f(xi)−yi∣L = \frac{1}{n} \sum_{i=1}^{n} |f(x_i) - y_i|L=n1i=1nf(xi)yi

特点

  • L1 loss 具有稀疏性,惩罚较大值,常作为正则项添加
  • ⚠️ 最大问题:梯度在零点不平滑,导致优化器可能跳过极小值点
import torch
import torch.nn as nn

y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)
y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)

loss = nn.L1Loss()
my_loss = loss(y_pred, y_true).detach().numpy()
print('loss:', my_loss)
4.2 MSE 损失函数(L2 Loss)

Mean Squared Error(MSE) 以误差平方和的均值作为距离,也叫欧氏距离

L=1n∑i=1n(f(xi)−yi)2L = \frac{1}{n} \sum_{i=1}^{n} (f(x_i) - y_i)^2L=n1i=1n(f(xi)yi)2

特点

  • L2 loss 也常作为正则项
  • ⚠️ 当预测值与目标值相差很大时,梯度容易爆炸
import torch
import torch.nn as nn

y_pred = torch.tensor([1.0, 1.0, 1.9], requires_grad=True)
y_true = torch.tensor([2.0, 2.0, 2.0], dtype=torch.float32)

loss = nn.MSELoss()
my_loss = loss(y_pred, y_true).detach().numpy()
print('myloss:', my_loss)
4.3 Smooth L1 损失函数

Smooth L1 是 L1 的"光滑版",本质是一个分段函数

L={0.5⋅x2∣x∣<1∣x∣−0.5∣x∣≥1L = \begin{cases} 0.5 \cdot x^2 & |x| < 1 \\ |x| - 0.5 & |x| \geq 1 \end{cases}L={0.5x2x0.5x<1x1

其中 x=f(x)−yx = f(x) - yx=f(x)y 为真实值和预测值的差值。

特点

  • [−1,1][-1, 1][1,1] 区间内用 L2 损失 → 解决 L1 的不光滑问题
  • [−1,1][-1, 1][1,1] 区间外用 L1 损失 → 解决离群点梯度爆炸的问题

简单说:Smooth L1 集中了 L1 和 L2 的优点,避免了两者的缺点,在目标检测(如 Faster R-CNN)中广泛使用。

import torch
import torch.nn as nn

y_true = torch.tensor([0, 3])
y_pred = torch.tensor([0.6, 0.4], requires_grad=True)

loss = nn.SmoothL1Loss()
my_loss = loss(y_pred, y_true).detach().numpy()
print('loss:', my_loss)

5. 损失函数分类汇总

任务类型 损失函数 PyTorch API 适用场景
多分类 交叉熵损失 (CrossEntropyLoss) nn.CrossEntropyLoss() 图像分类、文本多分类
二分类 sigmoid + BCELoss nn.BCELoss() 猫狗分类、垃圾邮件检测
回归 MAE / L1 Loss nn.L1Loss() 对离群点不敏感的场景
回归 MSE / L2 Loss nn.MSELoss() 常规回归任务
回归 Smooth L1 Loss nn.SmoothL1Loss() 目标检测、兼顾平滑与鲁棒

二、总结

损失函数对比

损失函数 公式 优点 缺点
CrossEntropyLoss −∑yklog⁡(S(f(x))k)-\sum y_k \log(S(f(x))_k)yklog(S(f(x))k) 概率解释,强梯度惩罚 需要 softmax 配合
BCELoss −(ylog⁡y^+(1−y)log⁡(1−y^))-(y\log\hat{y}+(1-y)\log(1-\hat{y}))(ylogy^+(1y)log(1y^)) 二分类专用 需要先过 sigmoid
MAE (L1) 1n∑i=1nxi−yi\frac{1}{n}\sum_{i=1}^{n}x_i - y_in1i=1nxiyi 鲁棒性强 梯度不平滑
MSE (L2) 1n∑(xi−yi)2\frac{1}{n}\sum(x_i-y_i)^2n1(xiyi)2 处处可导 对离群点敏感,梯度易爆炸
Smooth L1 分段函数 兼顾平滑与鲁棒 区间边界需注意
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐