在机器学习和深度学习中,损失函数是用来衡量模型参数的质量的函数,衡量的方式是比较网络输出和真实输出的差异:

1. 多分类损失函数
1.1 公式定义
在多分类任务通常使用 Softmax 将 logits 转换为概率的形式,所以多分类的交叉熵损失也叫做 Softmax 损失,计算方式如下:
首先,将模型的原始输出(logits)通过 Softmax 函数转换为概率分布:
其中:
- \(z_i\) 是第 \(i\) 类的 logit 值,
- \(C\) 是类别总数,
- \(p_i\) 是第 \(i\) 类的预测概率。
然后,计算真实标签与预测概率之间的交叉熵损失:
其中:
- \(y_i\) 是第 \(i\) 类的真实标签(one-hot 编码形式,即真实类别为 1,其余为 0),
- \(p_i\) 是第 \(i\) 类的预测概率,
- \(C\) 是类别总数。
通常将 Softmax 和交叉熵合并表示为:
其中 \(z_k\) 是真实类别对应的 logit 值。
1.2 计算示例
假设:
模型输出的 logits(未归一化的分数):
\[\mathbf{z} = [2.0, 1.0, 0.1] \]真实标签(one-hot 编码):
\[\mathbf{y} = [0, 1, 0] \]
首先,将 logits 通过 Softmax 函数转换为概率分布:
得到:
所以 Softmax 概率为:
即:
由交叉熵损失公式:
由于真实标签是 one-hot 编码(\(y_2 = 1\),其余为 0),所以只需计算真实类别对应的 \(-\log(p_2)\):
代码实现:
import torch
import torch.nn as nn
# 定义 logits 和真实标签(注意:这里 y 是类别索引,不是 one-hot)
z = torch.tensor([[2.0, 1.0, 0.1]], dtype=torch.float32) # 必须是 2D (batch_size, num_classes)
y = torch.tensor([1], dtype=torch.long) # 类别索引(1 表示第2类)
# 使用 nn.CrossEntropyLoss(自动包含 Softmax + 交叉熵)
criterion = nn.CrossEntropyLoss()
loss = criterion(z, y)
print("Logits:", z)
print("真实类别:", y.item()) # 1
print("交叉熵损失:", loss.item()) # ≈1.4182. 二分类损失函数
2.1 公式定义
在二分类任务中,通常使用 Sigmoid 函数将模型的原始输出(logit)转换为概率值,然后计算 二元交叉熵损失,具体步骤如下:
首先适用 Sigmoid 函数将 logit 转换为概率:
其中:
- \(z\) 是模型的原始输出(logit),
- \(p\) 是预测为正类(类别 1)的概率。
再计算元交叉熵损失:
其中:
- \(y\) 是真实标签(0 或 1),
- \(p\) 是预测为正类的概率。
特点:
- 当 \(y = 1\) 时,损失为 \(-\log(p)\)(希望 \(p\) 越大越好)。
- 当 \(y = 0\) 时,损失为 \(-\log(1 - p)\)(希望 \(p\) 越小越好)。
2.2 计算示例
假设:
- 模型输出的 logit:\[z = 0.8 \]
- 真实标签:\[y = 1 \]
- 计算 Sigmoid 概率:\[p = \frac{1}{1 + e^{-0.8}} \approx \frac{1}{1 + 0.449} \approx 0.690 \]
- 计算交叉熵损失:\[L = -\left[ 1 \cdot \log(0.690) + 0 \cdot \log(1 - 0.690) \right] \approx -\log(0.690) \approx 0.371 \]
代码实现:
import torch
import torch.nn as nn
# 定义 logit 和真实标签
z = torch.tensor([0.8], dtype=torch.float32) # 注意是 1D 或 2D
y = torch.tensor([1.0], dtype=torch.float32) # 二分类标签必须是浮点数
# 使用 nn.BCEWithLogitsLoss(内置 Sigmoid + 交叉熵)
criterion = nn.BCEWithLogitsLoss()
loss = criterion(z, y)
print("Logit:", z.item()) # 0.8
print("真实标签:", y.item()) # 1
print("Sigmoid 概率:", torch.sigmoid(z).item()) # ≈0.690
print("二元交叉熵损失:", loss.item()) # ≈0.3713. 回归MAE损失函数
3.1 公式定义
平均绝对误差(Mean Absolute Error, MAE)是一种用于回归任务的损失函数,MAE也被称为 L1 Loss,计算预测值与真实值之间绝对差值的平均值。
公式如下:
其中:
- \(y_i\) 是第 \(i\) 个样本的真实值,
- \(\hat{y}_i\) 是第 \(i\) 个样本的预测值,
- \(N\) 是样本数量。
特点:
- 鲁棒性:MAE 对异常值不敏感,因为它是绝对误差的平均值,不像均方误差(MSE)会放大异常值的影响。
- 梯度:MAE 的梯度是常数(±1),在优化时不会因为误差大小而改变步长,但在接近最小值时可能收敛较慢。
- 输出解释:MAE 的值与实际目标值的单位一致,直观易解释(例如,MAE=2 表示平均误差为 2 个单位)。
3.2 计算示例
假设:
- 真实值:\([3.0, -0.5, 2.0, 7.0]\)
- 预测值:\([2.5, 0.0, 2.0, 8.0]\)
计算绝对误差:
MAE 损失:
代码实现:
import torch
import torch.nn as nn
# 真实值和预测值(假设 batch_size=4)
y_true = torch.tensor([3.0, -0.5, 2.0, 7.0])
y_pred = torch.tensor([2.5, 0.0, 2.0, 8.0])
# 使用 PyTorch 的 L1Loss(即 MAE)
criterion = nn.L1Loss()
loss = criterion(y_pred, y_true)
print("MAE 损失:", loss.item()) # 输出 0.54. 回归MSE损失函数
4.1 公式定义
均方误差(Mean Squared Error, MSE)是回归任务中最常用的损失函数之一,MSE也被称为L2 Loss,计算预测值与真实值之间平方差值的平均值。
公式如下:
其中:
- \(y_i\) 是第 \(i\) 个样本的真实值,
- \(\hat{y}_i\) 是第 \(i\) 个样本的预测值,
- \(N\) 是样本数量。
特点:
- 对异常值敏感:MSE会放大较大误差的影响(因为平方操作),因此对异常值比MAE更敏感。
- 梯度特性:MSE的梯度与误差大小成正比(梯度为\(2(y_i - \hat{y}_i)\)),在误差较大时梯度也较大,有助于快速收敛,但在接近最小值时可能不稳定。
- 输出解释:MSE的单位是目标值的平方(例如,若目标单位是"米",MSE单位是"平方米"),因此需开平方(RMSE)才能与实际单位一致。
4.2 计算示例
假设:
- 真实值:\([3.0, -0.5, 2.0, 7.0]\)
- 预测值:\([2.5, 0.0, 2.0, 8.0]\)
计算平方误差:
MSE 损失:
代码实现:
import torch
import torch.nn as nn
# 真实值和预测值(假设 batch_size=4)
y_true = torch.tensor([3.0, -0.5, 2.0, 7.0])
y_pred = torch.tensor([2.5, 0.0, 2.0, 8.0])
# 使用 PyTorch 的 MSELoss
criterion = nn.MSELoss()
loss = criterion(y_pred, y_true)
print("MSE 损失:", loss.item()) # 输出 0.3755. 平滑L1损失函数
5.1 公式定义
平滑L1损失(Smooth L1 Loss)是L1 Loss(MAE)和L2 Loss(MSE)的结合体,由Ross Girshick在Fast R-CNN中提出。它在误差较小时使用平方项(类似MSE),在误差较大时使用线性项(类似MAE),兼具两者的优点。
公式如下:
其中:
特点:
- 鲁棒性:对异常值比MSE更鲁棒(大误差时退化为线性)
- 梯度平滑:在误差接近0时梯度逐渐减小(避免MSE在极小误差时的不稳定)
- 收敛性:比MAE在接近最优解时收敛更快(因小误差时使用二次项)
对比图像:

5.2 计算示例
假设:
- 真实值:\([1.2, -0.8, 3.0, -2.5]\)
- 预测值:\([0.9, -0.5, 2.6, -1.8]\)
- 阈值 \(\beta=1\)(默认值)
逐项计算:
\(|1.2-0.9|=0.3<1\) → \(0.5 \times 0.3^2 = 0.045\)
\(|-0.8-(-0.5)|=0.3<1\) → \(0.5 \times 0.3^2 = 0.045\)
\(|3.0-2.6|=0.4<1\) → \(0.5 \times 0.4^2 = 0.08\)
\(|-2.5-(-1.8)|=0.7<1\) → \(0.5 \times 0.7^2 = 0.245\)
总损失:
代码实现:
import torch
import torch.nn as nn
# 真实值和预测值
y_true = torch.tensor([1.2, -0.8, 3.0, -2.5])
y_pred = torch.tensor([0.9, -0.5, 2.6, -1.8])
# PyTorch的SmoothL1Loss(默认beta=1.0)
criterion = nn.SmoothL1Loss()
loss = criterion(y_pred, y_true)
print("Smooth L1 Loss:", loss.item()) # 输出 0.10375PyTorch中的 beta参数 控制二次项与线性项的分界点:
- 当
|y - ŷ| < beta时使用二次项 - 当
|y - ŷ| >= beta时使用线性项
不同beta值的影响:
# 示例:调整beta值
criterion_beta05 = nn.SmoothL1Loss(beta=0.5) # 更早切换到线性区域
criterion_beta2 = nn.SmoothL1Loss(beta=2.0) # 更晚切换到线性区域