最近在跑模型的时候,遇到了个问题,单独训练A loss ,模型可以达到想要的性能,训练B loss,也可以达到想要的性能,但是当A和B一起的时候,就两个任务都达不成了。搜了搜这个方向的论文,发现了这篇一千都引用的paper,试了一下,确实有点作用,故而记录一下。
论文题目:Gradient Surgery for Multi-Task Learning
代码地址:https://github.com/tianheyu927/PCGrad
因为是用于训练的论文,这里就不说很多有的没的故事了。简单来说,就是当发现在跑多任务的时候,如果发下任务冲突(文中的判断方式是余弦相似度为负)。那么就不能正常训练了。于是作者想了个办法,就是在传梯度的时候,对梯度做点小手术,把负向的梯度向下图所示,投影到正向上,这样不就余弦相似度是正的了么。然后试了一下,效果确实还挺管用。


论文的方法核心就是用公式1来解决梯度冲突的问题。不过官网的代码是tf的版本,我自己手写了一个pytorch的,方便使用。
上面代码是根据tf的代码化简写的,和本体可能有一定出入,仅供参考。
不过在使用pcgrad的时候,也是遇到了一些问题,特别的有下面2个点
- 对于多任务,作者代码中使用的是随机选取主任务然后对其他做梯度手术,但是一般做多个loss的时候,其实是有主导性的,哪个loss比较重要,哪个没这么重要,都有说法,直接随机可能导致最重要的任务训练不充分。
- 在做梯度手术的时候,对于内积为正,余弦方向相同的loss作者选择的是直接舍弃。但是就算方向完全相同,也不代表另一个loss不需要了,如果不加就能达成目的那根本就不需要多出来这额外的loss。这可能导致有些loss一直得不到优化。
后续准备再看看改进,有没有更好的解决方案吧,不过这篇论文工作确实不错,方法简单好用,值得推荐