解决办法是从损失函数入手使其一致,包括两个方面:
(1)看损失函数是用什么度量单位计算出来的,对其进行归一化处理,先让损失函数的输入保持一致的量纲。比如如果用余弦夹角计算的,本身就是[0,1]区间的,不用再处理。如果欧式距离,则对欧式距离进行归一化处理,比如用不带loss的Softmax进行归一化,caffe的欧式距离层里面也有直接归一化的设置。再比如输入直接是feature map,而feature map的值不是[0,1]的,则可以Softmax归一化,也可以根据其取值区间归一化。总之,先让loss的输入是相同区间的。
(2)损失函数的计算本身,比如是多个batch的总和,还是多个batch的平均,还是怎么算的。即看这3中loss计算方法是否一致,这个应该比较容易看出来,然后进行调整。比如一个loss是总和,其它两个loss是平均,那把总和那个除以batch_size就可以了。
下面给出 YOLOv5 中常用的三部分损失的具体计算公式和它们的实际意义:
1. 边界框回归损失(Box Regression Loss)
YOLOv5 通常采用 Complete IoU (CIoU) Loss,它不仅考虑了预测框与真实框的重叠(IoU),还综合了中心点距离和长宽比的一致性,从而使边界框回归更加精确。CIoU Loss 的公式为:
LCIoU=1−IoU+ρ2(b,bgt)c2+α v\mathcal{L}_{\text{CIoU}} = 1 - IoU + \frac{\rho^2(\mathbf{b}, \mathbf{b}^{gt})}{c^2} + \alpha\,vLCIoU=1−IoU+c2ρ2(b,bgt)+αv
其中:
- IoUIoUIoU:预测框 b\mathbf{b}b 与真实框 bgt\mathbf{b}^{gt}bgt 的交并比,反映了重叠区域的比例。
- ρ(b,bgt)\rho(\mathbf{b}, \mathbf{b}^{gt})ρ(b,bgt):预测框和真实框中心点之间的欧式距离。
- ccc:最小外接矩形的对角线长度,该矩形覆盖预测框和真实框。
- vvv:衡量宽高比一致性的指标,计算公式为: v=4π2(arctanwgthgt−arctanwh)2v = \frac{4}{\pi^2}\left(\arctan\frac{w^{gt}}{h^{gt}} - \arctan\frac{w}{h}\right)^2v=π24(arctanhgtwgt−arctanhw)2 其中 w, hw,\,hw,h 分别为预测框的宽和高,wgt, hgtw^{gt},\,h^{gt}wgt,hgt 为真实框的宽和高。
- α\alphaα:权重因子,用于平衡宽高比项,其定义为: α=v(1−IoU)+v\alpha = \frac{v}{(1-IoU) + v}α=(1−IoU)+vv
实际意义:
- 1−IoU1 - IoU1−IoU 部分直接反映预测与真实框之间的重叠情况;
- 中心距离项 ρ2c2\frac{\rho^2}{c^2}c2ρ2 促使预测框的中心与真实框更接近;
- 宽高比项 α v\alpha\,vαv 则使得预测框的形状尽可能与真实框匹配。
综合起来,CIoU Loss 能够更全面地衡量和引导边界框回归的准确性。
2. 目标置信度损失(Objectness Loss)
目标置信度损失用于判断每个预测框中是否存在目标,通常使用二值交叉熵(Binary Cross Entropy, BCE)Loss。其公式为:
Lobj=−∑i[yilog(pi)+(1−yi)log(1−pi)]\mathcal{L}_{\text{obj}} = -\sum_{i} \Big[y_i \log(p_i) + (1-y_i) \log(1-p_i)\Big]Lobj=−i∑[yilog(pi)+(1−yi)log(1−pi)]
其中:
- yiy_iyi 是第 iii 个预测框的真实目标标注(1 表示存在目标,0 表示背景)。
- pip_ipi 是模型预测的目标存在概率。
实际意义:
BCE Loss 在这里用来衡量预测的置信度与真实情况之间的差距,使模型在训练过程中能够正确地区分出包含目标和不包含目标的预测框。
3. 分类损失(Classification Loss)
对于目标类别的预测,YOLOv5 通常采用交叉熵(Cross Entropy)Loss或二值交叉熵(BCE)Loss(在多标签场景下)。以交叉熵 Loss 为例,其公式为:
Lcls=−∑c=1Cyclog(pc)\mathcal{L}_{\text{cls}} = -\sum_{c=1}^{C} y_c \log(p_c)Lcls=−c=1∑Cyclog(pc)
其中:
- CCC 是类别总数。
- ycy_cyc 是目标类别的真实分布(通常为 one-hot 编码)。
- pcp_cpc 是模型预测的类别概率分布。
实际意义:
交叉熵损失用于衡量模型在类别预测上的准确性,惩罚预测分布与真实分布之间的差异,从而引导模型学习正确的分类边界。
综合说明
在 YOLOv5 中,以上三种损失会根据预设的权重加权求和,形成总损失:
loss=λbox⋅LCIoU+λobj⋅Lobj+λcls⋅Lcls\text{loss} = \lambda_{\text{box}} \cdot \mathcal{L}_{\text{CIoU}} + \lambda_{\text{obj}} \cdot \mathcal{L}_{\text{obj}} + \lambda_{\text{cls}} \cdot \mathcal{L}_{\text{cls}}loss=λbox⋅LCIoU+λobj⋅Lobj+λcls⋅Lcls
其中 λbox\lambda_{\text{box}}λbox、λobj\lambda_{\text{obj}}λobj 和 λcls\lambda_{\text{cls}}λcls 是调节各部分对最终损失贡献的超参数。通过这种设计,YOLOv5 同时关注定位(边界框回归)、目标存在判断和类别预测,使得模型在整体优化时能够兼顾各个任务,提升检测精度和鲁棒性。
L1 Loss(平均绝对误差, MAE)
- 定义: L1=1N∑i=1N∣yi−y^i∣L1 = \frac{1}{N}\sum_{i=1}^N |y_i - \hat{y}_i|L1=N1i=1∑N∣yi−y^i∣
- 特点:
- 对异常值不敏感:L1 loss 对大误差的惩罚是线性的,因此当数据中存在异常值时,不会像 L2 loss 那样被大误差主导。
- 导数不连续:在误差为 0 的位置不可微(虽然在实现上一般会处理这个问题),可能会导致优化器在局部接近零时出现震荡。
- 能促进稀疏性:在某些问题中(例如特征选择、稀疏编码),L1 正则化可以促使模型产生稀疏解。
- 适用场景:
- 当数据中存在噪声或异常值时,使用 L1 loss 能使模型更加鲁棒。
- 当希望模型对预测误差不那么敏感于大值误差时。
L2 Loss(均方误差, MSE)
- 定义: L2=1N∑i=1N(yi−y^i)2L2 = \frac{1}{N}\sum_{i=1}^N (y_i - \hat{y}_i)^2L2=N1i=1∑N(yi−y^i)2
- 特点:
- 对大误差敏感:由于误差被平方,较大的偏差会产生更高的惩罚,有助于模型纠正较大的错误,但可能受异常值影响较大。
- 平滑可微:L2 loss 的导数连续且处处可微,使得基于梯度的优化方法更稳定。
- 优化时更容易求解:常用的闭式解(例如线性回归的正规方程)基于 L2 loss,适用于很多数值优化方法。
- 适用场景:
- 当数据噪声较少或不需要特别鲁棒的情形下,L2 loss 能使模型更好地收敛。
- 当需要对大误差施加更严格的惩罚时(例如对偏差较大的预测进行重点修正)。
如何选择?
-
数据特点:
- 数据中如果存在显著的异常值或噪声,选择 L1 loss 可能会更稳健;
- 数据较干净且希望减少大误差时,L2 loss 更为合适。
-
任务需求:
- 对于一些需要稀疏性或鲁棒性的任务(如部分特征选择),L1 loss 或者 L1 正则化(Lasso)是一个不错的选择;
- 对于回归任务、机器学习中的标准预测问题,L2 loss(MSE)是最常用的选择。
-
优化稳定性:
- L2 loss 的平滑性有助于梯度下降方法稳定收敛;
- L1 loss 的非光滑性在某些情况下可能需要特殊处理,比如使用次梯度(sub-gradient)或光滑近似方法。
总结
- L1 Loss:适用于异常值多、噪声大或者需要稀疏性表达的场景,能够减少大误差对模型的干扰,但其不连续的梯度可能在某些优化器中引起问题。
- L2 Loss:适用于数据干净、需要平滑梯度优化以及对大误差敏感的场景,但在异常值存在时可能过分惩罚,从而影响模型的鲁棒性。
在一些实际应用中,仅使用 L1 或 L2 loss 往往难以同时兼顾鲁棒性和稳定性,因此结合二者(例如使用 Elastic Net 或 Huber loss)能够发挥各自优势。以下是一些常见场景和原因:
1. 回归任务中的特征选择与稳定性
- 场景:
当数据中存在较多特征且部分特征存在共线性问题时,模型可能会过拟合或者难以解释。 - 原因:
- L1 loss(Lasso 正则化) 有助于稀疏化参数,自动进行特征选择,剔除冗余信息;
- L2 loss(Ridge 正则化) 则有助于稳定模型参数,缓解共线性问题。
- 结合方式:
Elastic Net 正则化就是典型的结合,公式为 λ1∥θ∥1+λ2∥θ∥22\lambda_1 \|\theta\|_1 + \lambda_2 \|\theta\|_2^2λ1∥θ∥1+λ2∥θ∥22 这种组合在实际应用中可以取得更好的预测效果和泛化性能。
2. 图像恢复与生成任务
- 场景:
在图像去噪、超分辨率或图像生成任务中,重建图像的细节和结构都是关键目标。 - 原因:
- L2 loss 能使得整体像素误差最小化,但可能导致图像模糊;
- L1 loss 则能更好地保留边缘信息和细节,但可能会产生噪点。
- 结合方式:
常用的方案是将 L1 和 L2 loss 按一定权重组合,使得模型既能获得较低的整体误差,又能保持细节的清晰度。
3. 稳健回归(鲁棒回归)
- 场景:
在存在离群点或噪声较大的数据中,纯 L2 loss 对离群值非常敏感,而纯 L1 loss 虽然鲁棒但优化不够平滑。 - 原因:
- Huber loss 就是结合了 L1 和 L2 loss 的优点:
- 当误差较小时采用 L2 loss 平滑优化;
- 当误差超过一定阈值时采用 L1 loss 降低离群点的影响。
- Huber loss 就是结合了 L1 和 L2 loss 的优点:
- 结合方式:
通过设置合适的阈值(delta)来平衡两者的作用,实现对大误差的鲁棒处理和小误差的稳定优化。
4. 多任务学习中的损失平衡
- 场景:
在多任务学习中,不同任务可能对应不同的损失函数,有时需要对单个任务的输出同时考虑鲁棒性和精细误差的最小化。 - 原因:
- 如果单独使用 L2 loss,某些任务可能对异常值过于敏感,导致梯度更新不平衡;
- 而单独使用 L1 loss 则可能无法提供足够的平滑性。
- 结合方式:
将 L1 和 L2 loss 结合,可以在对整体误差进行平滑优化的同时,减少对异常值的依赖,从而获得更稳健的多任务模型。
总结
结合 L1 与 L2 loss 的方法主要在于希望同时获得两者的优点:
- L1 loss 提供稀疏性和对离群值的鲁棒性;
- L2 loss 提供平滑的梯度和稳定的优化效果。
GradNorm 是一种用于多任务学习中平衡各任务训练速率和梯度大小的动态调整方法,其主要目标是让各个任务在共享参数上的梯度保持一个相对均衡的状态,从而避免某个任务因梯度过大而主导训练。下面是 GradNorm 的主要流程和步骤:
1. 初始化
- 任务损失与权重
假设有 TTT 个任务,每个任务有对应的损失 LiL_iLi(例如 L1,L2,…,LTL_1, L_2, \dots, L_TL1,L2,…,LT),并且为每个任务分配一个可调权重 wiw_iwi(初始时通常都设为1)。总损失定义为: Ltotal=∑i=1TwiLiL_{\text{total}} = \sum_{i=1}^{T} w_i L_iLtotal=i=1∑TwiLi
2. 计算各任务的梯度范数
- 梯度计算
对于每个任务 iii,计算加权损失 wiLiw_i L_iwiLi 关于共享参数 θ\thetaθ 的梯度,然后计算其梯度范数: Gi=∥∇θ(wiLi)∥G_i = \left\| \nabla_\theta (w_i L_i) \right\|Gi=∥∇θ(wiLi)∥ 这里的 GiG_iGi 反映了任务 iii 对共享部分参数更新的“力度”。
3. 计算相对训练速率
-
相对损失下降速率
ri(t)=Li(t)Li(0)r_i(t) = \frac{L_i(t)}{L_i(0)}ri(t)=Li(0)Li(t)
记录初始时刻(迭代0时)各任务的损失 Li(0)L_i(0)Li(0),并在后续迭代中计算当前损失 Li(t)L_i(t)Li(t)。定义相对训练速率:这个比率反映了任务 iii 的训练进度:下降较慢的任务 rir_iri 较大,下降较快的任务 rir_iri 较小。
-
平均相对训练速率
rˉ(t)=1T∑i=1Tri(t)\bar{r}(t) = \frac{1}{T}\sum_{i=1}^{T} r_i(t)rˉ(t)=T1i=1∑Tri(t)
计算所有任务相对速率的平均值:
4. 设定目标梯度范数
- 目标设定
为了平衡各任务的训练,定义目标梯度范数: G^i=Gˉ(ri(t)rˉ(t))α\hat{G}_i = \bar{G} \left(\frac{r_i(t)}{\bar{r}(t)}\right)^\alphaG^i=Gˉ(rˉ(t)ri(t))α 其中:- Gˉ=1T∑i=1TGi\bar{G} = \frac{1}{T}\sum_{i=1}^{T} G_iGˉ=T1∑i=1TGi 是当前所有任务梯度范数的平均值;
- α\alphaα 是一个超参数,用来控制调整的敏感度。通常 α>0\alpha > 0α>0;
5. 定义权重损失并更新权重
-
权重损失函数
Lgrad=∑i=1T∣Gi−G^i∣L_{\text{grad}} = \sum_{i=1}^{T} \left| G_i - \hat{G}_i \right|Lgrad=i=1∑TGi−G^i
定义一个损失,用于衡量实际梯度范数与目标梯度范数之间的偏差:或者采用平方误差形式:
Lgrad=∑i=1T(Gi−G^i)2L_{\text{grad}} = \sum_{i=1}^{T} \left( G_i - \hat{G}_i \right)^2Lgrad=i=1∑T(Gi−G^i)2 -
梯度更新
通过对 LgradL_{\text{grad}}Lgrad 关于 wiw_iwi 进行梯度下降,更新各任务的权重 wiw_iwi。这种更新使得权重不断调整,从而让各任务在共享参数上的梯度接近目标值,达到平衡状态。
6. 联合训练流程
- 正向传播:计算每个任务的损失 LiL_iLi。
- 加权求和:计算总损失 Ltotal=∑iwiLiL_{\text{total}} = \sum_i w_i L_iLtotal=∑iwiLi。
- 反向传播:计算共享参数的梯度,同时计算各任务损失的梯度范数 GiG_iGi。
- 计算相对速率:利用当前和初始损失计算 ri(t)r_i(t)ri(t) 和 rˉ(t)\bar{r}(t)rˉ(t)。
- 设定目标梯度:根据目标公式计算 G^i\hat{G}_iG^i。
- 更新权重:计算 LgradL_{\text{grad}}Lgrad 并对 wiw_iwi 进行更新。
- 迭代更新:继续下一次训练迭代,权重 wiw_iwi 动态调整后应用于下一次的总损失计算。
实际意义
- 平衡多任务训练:通过动态调整各任务的权重,GradNorm 可以避免某个任务因梯度过大而支配整个训练过程,从而使所有任务能够同步进步。
- 自适应调整:该方法能自动感知各任务的训练进展,并根据实际情况调整学习速率,减少手动调参工作。
- 稳定训练:使共享参数更新时各任务的贡献更均衡,从而有助于整体模型训练的稳定性和收敛速度。