Loss Functions

这么多Loss Function,为啥偏偏用这个呢?为了进一步提升模型的准确度,是时候系统地学习一下不同的Loss Functions了。

nn.L1Loss

直接计算估计值和目标的绝对值距离,因此$x$和$y$具有相同的形状。

$$
\ell(x, y) = { l_1,\dots,l_N }^\top, \quad
l_k = \left| x_k - y_k \right|
$$

L1Loss官方文档

nn.SmoothL1Loss

正如其名,这是一个稍微平缓一点的L1Loss,相比于MSELoss,它对离群点的敏感度不是这么高。

$$
\text{loss}(x, y) = \frac{1}{n} \sum_{i} z_{i}
$$

$$
z_{i} =
\begin{cases}
0.5(x_i - y_i)^2, & \text{if} |x_i - y_i| < 1 \
|x_i - y_i| - 0.5, & \text{otherwise}
\end{cases}
$$

其图像是这个样子的:

SmoothL1Loss官方文档

nn.MSELoss

全称均方根误差,计算$x$和$y$距离的平方。

$$
\ell (x, y) = { l_1, \dots l_n }^\top, \quad
l_k = (x_k - y_k)^2
$$

MSELoss官方文档

nn.NLLLoss

Negative log likelihood loss,计算多分类问题的时候经常(直接或间接)用到。

假设有一个多分类任务需要将图片分成C类,那么模型的输出是一个C维向量$x$,$x_k$表示第k类在模型看来是正确答案的可能性。一般而言目标需要设置成one-hot向量,但是PyTorch的API指定$y$为标量。

$$
\ell (x, y) = { l_1, \dots, l_n}^\top, \quad
l_k = -x_k[y]
$$

实际上NLLLoss还有一个权重参数weight,这在类别分布不均匀的时候比较有用。当遇到某一类别的出现次数较少的数据集,先在训练集上预估类别分布,然后手动确定每一类别的权重,再带权计算loss,可以防止模型偏袒一方。

$$
l_k = -weight[k] \times x_k[y]
$$

NLLLoss官方文档

nn.CrossEntropyLoss

先看一下公式定义,

$$
\text{loss}(x, class)
= -\log\left(\frac{\exp(x[class])}{\sum_j \exp(x[j])}\right)
= -x[class] + \log\left(\sum_j \exp(x[j])\right)
$$

从内到外观察这个公式,x[class]x[j]等实际上是在计算NLLLoss,而稍“外侧”的计算形式又是Softmax,最后再结合最外侧的$\log$简化计算,实际上这个损失函数就是nn.NLLLoss()nn.LogSoftmax的组合。

NLLLoss类似的,这个损失函数也可以带上权重。

CrossEntropyLoss官方文档

nn.BCELoss

nn.CrossEntropyLoss是计算多分类的损失函数,如果目标仅两个类别,就可以使用nn.BCELoss了。实际上该loss是nn.CrossEntropyLoss的特殊情况,或者说化简形式,因此不再赘述。

BCELoss官方文档

nn.BCEWithLogitsLoss

这个损失函数是Sigmoid函数和BCELoss的组合,并且其性能比直接使用Sigmoid拼接BCELoss更加好,毕竟当两者组合在一起的时候,因为对数的性质,就可以考虑用加法代替乘法了。

$$
\ell(x, y) = { l_1, \dots, l_n }^\top, \quad
l_k = - w_k \left[ y_k \cdot \log \sigma(x_k) + (1 - y_k) \cdot \log (1 - \sigma(x_k)) \right]
$$

从式子中可以看出,BCEWithLogitsLoss也是带权的。其实,手动改变权重不仅仅是为了让模型适应样本倾斜的数据集,通过改变权重,还可以更好地贴合某些评价指标。比如让权重更倾向于正例的话,模型训练结果的召回率就会变高;而权重倾向于负例,则可以提升准确性。

BCEWithLogitsLoss官方文档

nn.KLDivLoss

KL散度是用来衡量两个分布的相似程度的。具体的介绍可以参考我的另一篇博客交叉熵

KLDivLoss官方文档

nn.CTCLoss

这个损失函数似乎是用在语音识别任务上的,暂时还没有学习,等之后用到了再说吧~嘿嘿嘿