目录
1. 线性回归损失函数
1.1 MAE损失
1.2 MSE损失
2. CrossEntropyLoss
2.1 信息量
2.2 信息熵
2.3 KL散度
2.4 交叉熵
3. BCELoss
4. 总结
1. 线性回归损失函数
1.1 MAE损失
MAE(Mean Absolute Error,平均绝对误差)通常也被称为 L1-Loss,通过对预测值和真实值之间的绝对差取平均值来衡量他们之间的差异。。
MAE的公式如下:
其中:
-
n 是样本的总数。
-
是第 i 个样本的真实值。
-
是第 i 个样本的预测值。
-
是真实值和预测值之间的绝对误差。
特点:
-
鲁棒性:与均方误差(MSE)相比,MAE对异常值(outliers)更为鲁棒,因为它不会像MSE那样对较大误差平方敏感。
-
物理意义直观:MAE以与原始数据相同的单位度量误差,使其易于解释。
应用场景: MAE通常用于需要对误差进行线性度量的情况,尤其是当数据中可能存在异常值时,MAE可以避免对异常值的过度惩罚。
使用torch.nn.L1Loss
即可计算MAE:
import torch
import torch.nn as nn
# 初始化MAE损失函数
mae_loss = nn.L1Loss()
# 假设 y_true 是真实值, y_pred 是预测值
y_true = torch.tensor([3.0, 5.0, 2.5])
y_pred = torch.tensor([2.5, 5.0, 3.0])
# 计算MAE
loss = mae_loss(y_pred, y_true)
print(f'MAE Loss: {loss.item()}')
1.2 MSE损失
均方差损失,也叫L2Loss。
MSE(Mean Squared Error,均方误差)通过对预测值和真实值之间的误差平方取平均值,来衡量预测值与真实值之间的差异。
MSE的公式如下:
其中:
-
n 是样本的总数。
-
y_i 是第 i 个样本的真实值。
-
\hat{y}_i 是第 i 个样本的预测值。
-
\left( y_i - \hat{y}_i \right)^2 是真实值和预测值之间的误差平方。
特点:
-
平方惩罚:因为误差平方,MSE 对较大误差施加更大惩罚,所以 MSE 对异常值更为敏感。
-
凸性:MSE 是一个凸函数(国际的叫法,国内叫凹函数),这意味着它具有一个唯一的全局最小值,有助于优化问题的求解。
应用场景:
MSE被广泛应用在神经网络中。
使用 torch.nn.MSELoss 可以实现:
import torch
import torch.nn as nn
# 初始化MSE损失函数
mse_loss = nn.MSELoss()
# 假设 y_true 是真实值, y_pred 是预测值
y_true = torch.tensor([3.0, 5.0, 2.5])
y_pred = torch.tensor([2.5, 5.0, 3.0])
# 计算MSE
loss = mse_loss(y_pred, y_true)
print(f'MSE Loss: {loss.item()}')
2. CrossEntropyLoss
2.1 信息量
信息量用于衡量一个事件所包含的信息的多少。信息量的定义基于事件发生的概率:事件发生的概率越低,其信息量越大。其量化公式:
对于一个事件x,其发生的概率为 P(x),信息量I(x) 定义为:
性质
-
非负性:I(x)≥0。
-
单调性:P(x)越小,I(x)越大。
2.2 信息熵
信息熵是信息量的期望值。熵越高,表示随机变量的不确定性越大;熵越低,表示随机变量的不确定性越小。
公式由数学中的期望推导而来:
其中:
是信息量,
是信息量对应的概率
2.3 KL散度
KL散度用于衡量两个概率分布之间的差异。它描述的是用一个分布 Q来近似另一个分布 P时,所损失的信息量。KL散度越小,表示两个分布越接近。
对于两个离散概率分布 P和 Q,KL散度定义为:
其中:P 是真实分布,Q是近似分布。
2.4 交叉熵
对KL散度公式展开:
由上述公式可知,P是真实分布,H(P)是常数,所以KL散度可以用H(P,Q)来表示;H(P,Q)叫做交叉熵。
如果将P换成y,Q换成\hat{y},则交叉熵公式为:
其中:
-
C 是类别的总数。
-
y 是真实标签的one-hot编码向量,表示真实类别。
-
\hat{y} 是模型的输出(经过 softmax 后的概率分布)。
-
y_i 是真实类别的第 i 个元素(0 或 1)。
-
\hat{y}_i 是预测的类别概率分布中对应类别 i 的概率。
函数曲线图:
特点:
-
概率输出:CrossEntropyLoss 通常与 softmax 函数一起使用,使得模型的输出表示为一个概率分布(即所有类别的概率和为 1)。PyTorch 的 nn.CrossEntropyLoss 已经内置了 Softmax 操作。如果我们在输出层显式地添加 Softmax,会导致重复应用 Softmax,从而影响模型的训练效果。
-
惩罚错误分类:该损失函数在真实类别的预测概率较低时,会施加较大的惩罚,这样模型在训练时更注重提升正确类别的预测概率。
-
多分类问题中的标准选择:在大多数多分类问题中,CrossEntropyLoss 是首选的损失函数。
应用场景:
CrossEntropyLoss 广泛应用于各种分类任务,包括图像分类、文本分类等,尤其是在神经网络模型中。
nn.CrossEntropyLoss基本原理:
由交叉熵公式可知:
因为y_i是one-hot编码,其值不是1便是0,又是乘法,所以只要知道1对应的index就可以了,展开后:
其中,m表示真实类别。
因为神经网络最后一层分类总是接softmax,所以可以把\hat{y}_m直接看为是softmax后的结果。
所以,CrossEntropyLoss
实质上是两步的组合:Cross Entropy = Log-Softmax + NLLLoss
-
Log-Softmax:对输入 logits 先计算对数 softmax:
log(softmax(x))
。 -
NLLLoss(Negative Log-Likelihood):对 log-softmax 的结果计算负对数似然损失。简单理解就是求负数。原因是概率值通常在 0 到 1 之间,取对数后会变成负数。为了使损失值为正数,需要取负数。
对于softmax(x_i),在softmax介绍中了解到,需要减去最大值以确保数值稳定。
则:
所以:
总的交叉熵损失函数是所有样本的平均值:
示例代码如下:
import torch
import torch.nn as nn
# 假设有三个类别,模型输出是未经softmax的logits
logits = torch.tensor([[1.5, 2.0, 0.5], [0.5, 1.0, 1.5]])
# 真实的标签
labels = torch.tensor([1, 2]) # 第一个样本的真实类别为1,第二个样本的真实类别为2
# 初始化CrossEntropyLoss
# 参数:reduction:mean-平均值,sum-总和
criterion = nn.CrossEntropyLoss()
# 计算损失
loss = criterion(logits, labels)
print(f'Cross Entropy Loss: {loss.item()}')
在这个例子中,CrossEntropyLoss 直接作用于未经 softmax 处理的 logits 输出和真实标签,PyTorch 内部会自动应用 softmax 激活函数,并计算交叉熵损失。
分析示例中的代码:
logits = torch.tensor([[1.5, 2.0, 0.5], [0.5, 1.0, 1.5]])
第一个样本的得分是 [1.5, 2.0, 0.5]
,分别对应类别 0、1 和 2 的得分。
第二个样本的得分是 [0.5, 1.0, 1.5]
,分别对应类别 0、1 和 2 的得分
labels = torch.tensor([1, 2])
第一个样本的真实类别是 1。
第二个样本的真实类别是 2。
CrossEntropyLoss
的计算过程可以分为以下几个步骤:
(1) LogSoftmax 操作
首先,对每个样本的 logits 应用 LogSoftmax
函数,将 logits 转换为概率分布。LogSoftmax
函数的公式是: LogSoftmax(x_i) =x_i-\max(x)-log(\sum_{j=1}^ne^{x_j-\max(x)})
对于第一个样本 [1.5, 2.0, 0.5]
:
减去最大值:
计算:
求和并取对数:
计算 log_softmax
:
对于第二个样本 [0.5, 1.0, 1.5]
:
减去最大值:
计算:
求和并取对数:
计算 log_softmax
:
(2) 计算每个样本的损失
接下来,根据真实标签 z_t 计算每个样本的交叉熵损失。交叉熵损失的公式是:
对于第一个样本:
-
真实类别是 1,对应的 softmax 值是 -0.6041。
对于第二个样本:
-
真实类别是 2,对应的 softmax 值是 -0.6803。
(3) 计算平均损失
最后,计算所有样本的平均损失:
3. BCELoss
二分类交叉熵损失函数,使用在输出层使用sigmoid激活函数进行二分类时。
由交叉熵公式:
对于二分类问题,真实标签 y的值为(0 或 1),假设模型预测为正类的概率为 \hat{y},则:
所以:
示例:
import torch
import torch.nn as nn
# y 是模型的输出,已经被sigmoid处理过,确保其值域在(0,1)
y = torch.tensor([[0.7], [0.2], [0.9], [0.7]])
# targets 是真实的标签,0或1
t = torch.tensor([[1], [0], [1], [0]], dtype=torch.float)
# 计算损失方式一:
bceLoss = nn.BCELoss()
loss1 = bceLoss(y, t)
#计算损失方式二: 两种方式结果相同
loss2 = nn.functional.binary_cross_entropy(y, t)
print(loss1, loss2)
逐样本计算
样本 | y_i | t_i | 计算项 t_i * log(y_i) + (1-t_i) * log(1-y_i) |
---|---|---|---|
1 | 0.7 | 1 | 1*log(0.7) + 0*log(0.3) ≈ -0.3567 |
2 | 0.2 | 0 | 0*log(0.2) + 1*log(0.8) ≈ -0.2231 |
3 | 0.9 | 1 | 1*log(0.9) + 0*log(0.1) ≈ -0.1054 |
4 | 0.7 | 0 | 0*log(0.7) + 1*log(0.3) ≈ -1.2040 |
计算最终损失
4. 总结
-
当输出层使用softmax多分类时,使用交叉熵损失函数;
-
当输出层使用sigmoid二分类时,使用二分类交叉熵损失函数, 比如在逻辑回归中使用;
-
当功能为线性回归时,使用均方差损失-L2 loss;