Loss Functions
这么多Loss Function,为啥偏偏用这个呢?为了进一步提升模型的准确度,是时候系统地学习一下不同的Loss Functions了。
- nn.L1Loss
- nn.SmoothL1Loss
- nn.MSELoss
- nn.NLLLoss
- nn.CrossEntropyLoss
- nn.BCELoss
- nn.BCEWithLogitsLoss
- nn.KLDivLoss
- nn.CTCLoss
nn.L1Loss
直接计算估计值和目标的绝对值距离,因此$x$和$y$具有相同的形状。
$$
\ell(x, y) = { l_1,\dots,l_N }^\top, \quad
l_k = \left| x_k - y_k \right|
$$
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}
$$
其图像是这个样子的:
nn.MSELoss
全称均方根误差,计算$x$和$y$距离的平方。
$$
\ell (x, y) = { l_1, \dots l_n }^\top, \quad
l_k = (x_k - y_k)^2
$$
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]
$$
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类似的,这个损失函数也可以带上权重。
nn.BCELoss
nn.CrossEntropyLoss
是计算多分类的损失函数,如果目标仅两个类别,就可以使用nn.BCELoss
了。实际上该loss是nn.CrossEntropyLoss
的特殊情况,或者说化简形式,因此不再赘述。
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
也是带权的。其实,手动改变权重不仅仅是为了让模型适应样本倾斜的数据集,通过改变权重,还可以更好地贴合某些评价指标。比如让权重更倾向于正例的话,模型训练结果的召回率就会变高;而权重倾向于负例,则可以提升准确性。
nn.KLDivLoss
KL散度是用来衡量两个分布的相似程度的。具体的介绍可以参考我的另一篇博客交叉熵。
nn.CTCLoss
这个损失函数似乎是用在语音识别任务上的,暂时还没有学习,等之后用到了再说吧~嘿嘿嘿