来源:(22 封私信 / 80 条消息) 多任务学习中各loss权重应该如何设计呢? - 知乎 (zhihu.com)
多损失在深度学习中很常见,例如:
- 目标检测:以 YOLO 为例,它的损失函数一般都是由几部分构成,包括中心坐标误差损失、宽高坐标误差损失宽高坐标误差损失宽高坐标误差损失、置信度误差损失。这里面又涉及到一个前景和背景的问题,即当前网格存不存在目标,损失函数计算方式会有所不同,如此一来就需要控制两者的比例,避免梯度被某个任务主导。
- 语义分割:特别地,针对医学影像这种前景背景差异非常小的任务,通常很多方法都会引入深监督的机制,这样一来就不单单是两级 loss 了,几乎每个 stage 都会引申出一条分支出来。遇到这种情况你总不能排列组合去炼丹吧?
多损失问题涉及了多任务学习Network Architecture(how to share) 和Loss Function(how to balance)这两个挑战。
(1)把各loss统一到同一个数量级上,其背后的原因是不同任务的不同损失函数尺度有很大的差异,因此需要考虑用权值将每个损失函数的尺度统一。一般情况下,不同 task 收敛过程中梯度大小是不一样的,对不同学习率的敏感程度也是不一样的。把各loss统一到同一个数量级,可以避免梯度小的loss被梯度大的loss所带走,使得学习到的feature有较好的泛化能力。
这个问题比较新的解决办法,可以参考cvpr2018的一个工作《Multi-Task Learning Using Uncertainty to Weigh Losses for Scene Geometry and Semantics》,这篇文章提出利用同方差的不确定性,将不确定性作为噪声,进行训练。
(2)Network Architecture一般有:Hard-parameter sharing和Soft-parameter-sharing。Hard-parameter sharing有一组相同的特征共享层,这种设计大大减少了过拟合的风险;Soft-parameter sharing每一个任务都有自己的特征参数和每个子任务之间的约束。而对于“不同网络部分梯度的数量级”问题,虽然梯度值相同,但不同的loss在task上的表现也是不同的,所以还是要找不同loss的合适平衡点。
对于Network Architecture and Loss Function的关系,经过大量实验和经验总结后,发现一个好的Network Design比一个好的Loss Design更能有效增加featrue的泛化能力,一个好的Dataset比一个好的Network Design又更能有效增加feature的泛化能力。
最后,展示一下我们使用Multi-task learning训练Face Reconstruction and Dense Alignment的例子。简单说明下:这个模型中一共有4个task,dense alignment部分一共有4w个关键点,并且可以眨眼、可以张嘴。
https://github.com/Star-Clouds/FRDAgithub.com/Star-Clouds/FRDA
多任务学习
定义
多任务学习(Multi-Task Learing, MTL)是机器学习中一个活跃的研究领域。它是一种学习范式,旨在通过利用它们之间的共同知识来共同学习多个相关任务以提高它们的泛化性能。近年来,许多研究人员成功地将 MTL 应用到计算机视觉、自然语言处理、强化学习、推荐系统等不同领域。目前对 MTL 的研究主要集中在两个角度,网络架构设计和损失加权策略。
网络架构设计
在网络架构的设计中,最简单和最流行的方法是硬参数共享(HPS,LibMTL.architecture.HPS),如图1所示,其中编码器在所有任务之间共享,每个任务都有自己的编码器以及特定的解码器。由于大部分参数在任务之间共享,因此当任务之间的相关性不够大时,这种架构很容易导致负共享(即一损俱损)。为了更好地处理任务之间的关系,已经提出了不同的 MTL 架构。
图1
上图中左边是单输入问题右边是多输入问题的图示,以
硬参数共享模式为例。目前 LibMTL 已经支持多种最先进的架构,详情请参阅 LibMTL.architecture 分支。
损失加权策略
平衡多个任务对应的多个损失是处理任务关系的另一种方式,因为共享参数由所有任务损失更新。因此,已经提出了不同的方法来平衡损失或梯度。
目前 LibMTL 已支持多种最先进的加权策略,详情请参阅 LibMTL.weighting 分支。
例如,一些基于梯度平衡的方法如 MGDA 需要先计算每个任务的梯度,然后通过各种方式计算聚合梯度。为了降低计算成本,它可以使用编码器后表示的梯度(简称为 rep-grad)来近似共享参数的梯度(简称为 param-grad)。
rep-grad 的 PyTorch 实现如图2所示。我们需要通过 detach 操作将计算图分离成两部分。LibMTL
内部已经将这两种情况统一到一个训练框架中,因此我们只需要正确设置命令行参数 rep_grad 即可。此外,参数 rep_grad 与 multi_input 不冲突。
图2
上述示例图清晰的说明了如何计算表示的梯度。
LibMTL
LibMTL[1] 是一个基于 PyTorch 构建的用于多任务学习的开源库。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)