损失函数
均方误差损失
均方误差损失,MSELoss,用于回归任务,计算预测值和真实值之间的均方误差
1 |
|
reduction
:指定如何对输出进行降维,可选值为none
、mean
和sum
none
:不进行降维,返回每个样本的损失mean
:返回损失的均值,这是默认行为sum
:返回损失的总和
对创建的MSELoss
对象传入预测值和真实值张量,确保预测值和真实值的形状相同,返回均方误差损失张量
比如:
1 |
|
输出结果:
1 |
|
平均绝对值误差损失
与 MSE 相比,L1Loss 对异常值不那么敏感,因为它是基于绝对误差而不是平方误差
1 |
|
reduction
:指定如何对输出进行降维,可选值为none
、mean
和sum
none
:不进行降维,返回每个样本的损失mean
:返回损失的均值,这是默认行为sum
:返回损失的总和
对创建的L1Loss
对象传入预测值和真实值张量,确保预测值和真实值的形状相同,返回均方误差损失张量
比如:
1 |
|
输出结果:
1 |
|
交叉熵损失
1 |
|
参数:
weight
:一个可选的向量,用于为每个类别的损失赋予不同的权重。这对于处理类别不平衡的数据集很有用。ignore_index
:指定一个标签值,该值在计算损失时会被忽略。reduction
:指定如何对输出进行降维,可选值为none
、mean
和sum
none
:不进行降维,返回每个样本的损失mean
:返回损失的均值,这是默认行为sum
:返回损失的总和
CrossEntropyLoss
首先对预测输出应用LogSoftmax
,将预测输出转换为概率分布的对数形式。然后计算每个样本的负对数似然损失。最后,根据reduction
参数对结果进行降维
在损失函数中使用LogSoftmax
而不是直接在模型中使用Softmax
的原因:
softmax函数: \[ \hat y_j = \frac{\exp(o_j)}{\sum_k\exp(o_k)} \] 其中\(\hat y_j\)是预测的概率分布,\(o_j\)是未规范化的预测\(\mathbf{o}\)的第\(j\)个元素。
如果\(o_k\)中的一些数值非常大,那么\(\exp(o_k)\)可能大于数据类型容许的最大数字,即上溢(overflow)。这将使分母或分子变为inf
(无穷大),最后得到的是0、inf
或nan
(不是数字)的\(\hat y_j\)
解决这个问题的一个技巧是:在继续softmax计算之前,先从所有\(o_k\)中减去\(\max(o_k)\): \[ \begin{aligned} \hat y_j &= \frac{\exp(o_j)}{\sum_k\exp(o_k)}\\ &= \frac{e^{o_j}}{\sum_k e^{o_k}}\\ &= \frac{e^{o_j-\max(o_k)+\max(o_k)}}{\sum_k e^{o_k-\max(o_k)+\max(o_k)}}\\ &= \frac{e^{o_j-\max(o_k)}e^{\max(o_k)}}{e^{\max(o_k)}\sum_k e^{o_k-\max(o_k)}}\\ &= \frac{e^{o_j-\max(o_k)}}{\sum_k e^{o_k-\max(o_k)}}\\ &= \frac{\exp(o_j-\max(o_k))}{\sum_k\exp(o_k-\max(o_k))} \end{aligned} \]
在减法和规范化步骤后,可能有些\(o_j-\max(o_k)\)具有较大的负值。由于精度受限,\(\exp(o_j-\max(o_k))\)将有接近零的值,即下溢(underflow)。这些值可能会四舍五入为零,使\(\hat y_j\)为零,并且使得\(\log(\hat
y_j)\)的值为-inf
,反向传播时可能造成梯度爆炸
尽管我们要计算指数函数,但我们最终在计算交叉熵损失时会取它们的对数。我们可以将这两个结合在一起:
\[
\begin{aligned}
\log(\hat y_j) &=
\log\bigg(\frac{\exp(o_j-\max(o_k))}{\sum_k\exp(o_k-\max(o_k))}\bigg)\\
&= \log\big(\exp(o_j-\max(o_k))\big) -
\log\Bigg(\sum_k\exp(o_k-\max(o_k))\Bigg)\\
&= o_j-\max(o_k) - \log\Bigg(\sum_k\exp(o_k-\max(o_k))\Bigg)
\end{aligned}
\]
因此,在训练时,我们的神经网络中不会有Softmax,而是直接在CrossEntropyLoss
中计算LogSoftmax
,NLLLoss
(负对数似然损失)
CrossEntropyLoss
对象传入的y_hat
和y
应该满足如下要求:
y_hat
(模型输出):- 形状:
y_hat
应该是一个二维张量(Tensor),形状为(N, C)
,其中N
是批量大小(batch size),C
是类别的数量 - 数值:
y_hat
应该是模型的原始输出,通常是经过线性层(如全连接层)的输出,但没有应用 softmax 函数。CrossEntropyLoss
内部会自动应用LogSoftmax
- 类型:
y_hat
的数据类型通常是浮点数(如torch.float32
)
- 形状:
y
(真实标签):- 形状:
y
可以是一个一维张量(Tensor),形状为(N,)
,其中每个元素是一个类别索引(从 0 到C-1
)。也可以是一个二维张量,形状为(N, 1)
,但内部元素仍然是一个类别索引 - 数值:
y
中的每个元素都应该是一个整数,表示对应样本的真实类别索引 - 类型:
y
的数据类型通常是长整型(如torch.long
),因为它们是类别索引
- 形状:
比如:
1 |
|
在设计神经网络时,不需要softmax层,不仅是在训练时使用softmax很可能会导致上溢或下溢,在推理时,如果我们仅关心预测的类别,线性输出的最大值就代表了softmax后概率的最大值,可以直接取线性输出的最大值索引
二元交叉熵损失
1 |
|
参数:
weight
:Tensor
类型,可选。对每个样本的损失值进行加权,常用于处理类别不平衡问题。例如,若正样本数量较少,可通过增大正样本权重来平衡训练。必须是一维张量,形状与输入数据相同。若不指定,默认所有样本权重为1reduction
:str
类型,可选。指定损失值的聚合方式:none
:不聚合,返回每个样本的损失值mean
:计算所有样本损失的均值(默认)sum
:计算所有样本损失的总和
BCELoss()
对象传入的y_hat
和y
应该满足如下要求:
y_hat
(模型输出):二维张量,形状为(N, 1)
,也可以是一维张量,形状为(N,)
,其中N
是批量大小(batch size),每个元素是对应数据的预测概率(即模型最后必须通过Sigmoid
压缩到[0, 1]
区间,否则可能导致数值溢出或梯度异常)y
(真实标签):可以是一维张量,形状为(N,)
,也可以是二维张量,形状为(N, 1)
,每个元素是对应数据的真实概率(0或1,要求是浮点类型的张量)
y_hat
与y
的维度形状必须相同
比如:
1 |
|
1 |
|