day24_人工神经网络_损失函数
一、损失函数
1. 什么是损失函数
损失函数(Loss Function) 在深度学习中是用来衡量模型参数质量的函数,衡量方式是比较网络输出和真实输出的差异。简单来说:损失越小,模型预测越准;损失越大,模型预测越离谱。
2. 多分类任务损失函数
多分类任务中,通常使用 softmax 将 logits(网络原始输出)转换为概率形式,因此多分类的交叉熵损失也叫 softmax 损失。
L=−∑kyklog(S(f(x))k)L = -\sum_{k} y_k \log(S(f(x))_k)L=−k∑yklog(S(f(x))k)
其中:
- yyy 是样本 xxx 属于某一类别的真实概率(通常 one-hot 编码)
- f(x)f(x)f(x) 是样本属于某一类别的预测分数( logits)
- SSS 是 softmax 激活函数,将预测分数转换成概率
从概率角度理解:我们的目的是最小化正确类别所对应预测概率的对数的负值,也就是让模型对正确类别的预测概率越高越好。
在 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^)+(1−y)log(1−y^))
其中:
- 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=1∑n∣f(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=1∑n(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.5⋅x2∣x∣−0.5∣x∣<1∣x∣≥1
其中 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 | −(ylogy^+(1−y)log(1−y^))-(y\log\hat{y}+(1-y)\log(1-\hat{y}))−(ylogy^+(1−y)log(1−y^)) | 二分类专用 | 需要先过 sigmoid |
| MAE (L1) | 1n∑i=1nxi−yi\frac{1}{n}\sum_{i=1}^{n}x_i - y_in1∑i=1nxi−yi | 鲁棒性强 | 梯度不平滑 |
| MSE (L2) | 1n∑(xi−yi)2\frac{1}{n}\sum(x_i-y_i)^2n1∑(xi−yi)2 | 处处可导 | 对离群点敏感,梯度易爆炸 |
| Smooth L1 | 分段函数 | 兼顾平滑与鲁棒 | 区间边界需注意 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)