多任务损失函数浅谈多任务中的损失函数如何定义与优化

Posted 征途黯然.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多任务损失函数浅谈多任务中的损失函数如何定义与优化相关的知识,希望对你有一定的参考价值。

· 本文目录

  1、损失函数反向传播的关系
  2、添加系数的损失函数会影响实验结果(实验证明)
  3、多任务中损失函数与反向传播的思考
  4、学习多任务模型损失函数的思路

【注】写论文要优化多任务的损失函数,记录下最近的收获,应该能启发一些朋友。不足之处望指正。

[1] 损失函数反向传播的关系

  首先要明确,让损失函数的值最小是一个模型学习的目标,而反向传播只是优化模型时求梯度(求导)的一种手段

  反向传播算法的目的是什么? 就是通过更新神经网络的参数也就是每一层的权值、阈值来对损失函数进行最小化。主要方法求出损失函数对参数的梯度,只不过直接用损失函数求出参数的梯度非常困难,我们选择一层一层求损失函数对参数的梯度,更新完这一层的参数再往后传播。

  反向传播算法的作用是什么? 神经网络模型的学习算法一般是SGD。SGD需要用到损失函数C关于各个权重参数 w j k 、 b j w_jk、b_j wjkbj的偏导数 ∂ C ∂ w j k 、 ∂ C ∂ b j \\frac\\partial C\\partial w_jk 、\\frac\\partial C\\partial b_j wjkCbjC。一个模型的参数w,b是非常多的,故而需要反向传播算法快速计算 ∂ C ∂ w j k 、 ∂ C ∂ b j \\frac\\partial C\\partial w_jk 、\\frac\\partial C\\partial b_j wjkCbjC。也就是说反向传播算法是一种计算偏导数的方法。

  为什么要提出反向传播算法? 在反向传播算法提出之前人们应该想到了使用SGD学习模型,也想到了一些办法求解网络模型的偏导数,但这些算法求解效率比较低,所以提出反向传播算法来更高效的计算偏导数。(那时的网络模型还比较浅只有2-3层,参数少。估计即便不适用反向传播这种高效的算法也能很好的学习。一旦有人想使用更深的网络自然会遇到这个偏导数无法高效计算的问题,提出反向传播也就势在必行了)

[2] 添加系数的损失函数会影响实验结果(实验证明)

  我们说到所有参数的梯度,是基于损失函数来求的。所以如果仅仅是给损失函数前加个常数系数,每个参数的梯度都会有常数系数倍的变化,理论上会改变实验结果。

  我们采用RCNN模型,在路透社多标签数据集上进行实验。

  正常的损失函数如下:

# 计算多标签损失
def Loss(outputs, labels):
    loss_f = nn.BCEWithLogitsLoss()
    loss = loss_f(outputs, labels.float())
    return loss

  加了常数系数的损失函数如下:

# 计算多标签损失
def Loss(outputs, labels):
    loss_f = nn.BCEWithLogitsLoss()
    loss = 0.08*loss_f(outputs, labels.float())
    return loss

【注】这里的系数是随便设的,不是1和0就行。除此之外,实验是可复现的,随机种子都已固定,其他参数都相同。

  最终我们观察到两次实验结果:

Test Acc: 81.13%, Test Pre: 89.63%, Test Rec: 88.61%, Test F1: 88.02%, Test OE: 10.71% # 正常loss
Test Acc: 82.87%, Test Pre: 90.77%, Test Rec: 89.63%, Test F1: 89.26%, Test OE:  7.14% # 加了系数loss

  两次实验结果的不同,说明损失函数仅仅是变了一点(加个常数系数),就会对实验造成影响。

  如何理解这种现象?

  给损失函数加系数,在反向传播时,梯度必然会变化,同样的学习率在不同的梯度下,就会有不同的学习结果。
  对于单任务模型,把这个系数当作是一个超参数去调参的话,我觉得意义不大,这就变成了我们自己去定义损失函数了。而且我们自己修改的损失函数也不一定有泛化能力。

  但是把这种系数放到多任务中去调参,是较为可行的。

[3] 多任务中损失函数与反向传播的思考

  在多任务中一般是两种方法来定义损失函数:

  1、子任务的损失函数直接相加; L = L 1 + L 2 L = L_1 + L_2 L=L1+L2
  2、子任务的损失函数加权相加。 L = α ∗ L 1 + β ∗ L 2 L = \\alpha*L_1 + \\beta*L_2 L=αL1+βL2

  第二种方法通常比第一种要好。我们来讨论原因:(设此时有2个多任务, L 1 L_1 L1是任务一的损失, L 2 L_2 L2是任务2的损失)

  从梯度是损失函数对参数的求偏导来看,当我们想更新任务一里面的参数时,应该用 L 1 L_1 L1对参数求偏导最好,但是此时损失函数是 L = L 1 + L 2 L = L_1 + L_2 L=L1+L2不再是 L 1 L_1 L1,求偏导后就引入了 L 2 L_2 L2对任务一里面的参数的偏导。这样当然会降低模型的性能,所以我们可以为 L 1 L_1 L1 L 2 L_2 L2加权,某种程度来说,这是“降低”一个损失函数对一个不相干的任务在反向传播时的影响。也可以理解为两个任务的梯度有不同的“尺度”,两者的“尺度”差异较大时,一个任务对反向传播时参数更新的影响可能会盖过另外一个任务。

  但是采用加权的损失函数 L = α ∗ L 1 + β ∗ L 2 L = \\alpha*L_1 + \\beta*L_2 L=αL1+βL2,参数 α 、 β \\alpha 、\\beta αβ就变成了需要调整的超参数,它们的设置和任务的“尺度”、学习率、任务的损失大小等等都有些关系,甚至还要去考虑模型泛化的能力。想要去调一手好参,还是比较难的。

  所以这时提出第三种损失函数,把损失函数前的权重当作是可以学习的参数来学习。

[4] 学习多任务模型损失函数的思路

  此时去学习 L = α ∗ L 1 + β ∗ L 2 L = \\alpha*L_1 + \\beta*L_2 L=αL1+βL2中的参数 α 、 β \\alpha 、\\beta αβ是不可行的,因为它没有极值,直接把参数 α 、 β \\alpha 、\\beta αβ学成0就没得玩了。

  最起码要加上惩罚项,比如说: L = α ∗ L 1 + β ∗ L 2 + 1 α + 1 β L = \\alpha*L_1 + \\beta*L_2 + \\frac1\\alpha + \\frac1\\beta L=αL1+βL2+α1+β1,这样至少不会让参数 α 、 β \\alpha 、\\beta αβ没得可学。

  但是这样仍然不够,我们需要从理论推导的角度,去找到一些科学的损失函数学习公式。

  对于回归任务单标签分类任务来说,我们可以使用同方差不确定性来替代简单的权重系数来学习。

【注】可以参考博客:多任务学习中损失函数权重的自动调整 写的挺好的。

  我们也可以使用异方差不确定性来替代简单的权重系数来学习,和同方差大同小异。

【注】
同方差参考论文:Multi-Task Learning Using Uncertainty to Weigh Losses for Scene Geometry and Semantics
异方差参考论文:Uncertainty in multitask learning: joint representations for probabilistic MR-only radiotherapy planning

以上是关于多任务损失函数浅谈多任务中的损失函数如何定义与优化的主要内容,如果未能解决你的问题,请参考以下文章

多标签分类中的损失函数与评价指标

线性回归

一文搞懂深度常用损失函数

神经网络中的各种损失函数介绍

深度学习中分类任务的损失函数详解

深度学习中分类任务的损失函数详解